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
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9856484a0dcf/
Changeset: 9856484a0dcf
User: jmchilton
Date: 2014-04-21 21:28:47
Summary: Pack scripts.
Affected #: 1 file
diff -r 4df5e43d865176cdeb929db7fbf18c3b9af98591 -r 9856484a0dcf784ff4bf9e087c14de2e4d6d9506 static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes}});var InputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.multiple=a.multiple},can_accept:function(a){if(this.connectors.length<1||this.multiple){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(c){var b=this;nodeView=b.nodeView;this.tool_state=c.tool_state;this.form_html=c.form_html;this.tool_errors=c.tool_errors;this.annotation=c.annotation;var d=$.parseJSON(c.post_job_actions);this.post_job_actions=d?d:{};b.nodeView.renderToolErrors();var f=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();$.each(c.data_inputs,function(h,g){b.nodeView.replaceDataInput(g,a)});f.replaceWith(a);f.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body)},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(c){var d=new InputTerminalView({node:this.node,input:c});var f=d.el;var b=new DataInputView({terminalElement:f,input:c,nodeView:this,});var a=b.$el;var f=b.terminalElement;this.$(".inputs").append(a.prepend(f))},replaceDataInput:function(c,f){var g=new InputTerminalView({node:this.node,input:c});var d=g.el;this.$("div[name='"+c.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var h=this.terminal.connectors[0];if(h){d.terminal.connectors[0]=h;h.handle2=d.terminal}});$(this).remove()});var b=new DataInputView({terminalElement:d,input:c,nodeView:this,skipResize:true,});var a=b.$el;f.append(a.prepend(d))},addDataOutput:function(a){var c=new OutputTerminalView({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(b.terminalElement))}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var d=this.nodeView.node;if(a.extensions.indexOf("input")<0){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(d.type=="tool"){var f=new OutputCalloutView({label:b,output:a,node:d,});this.$el.append(f.el);this.$el.hover(function(){f.hoverImage()},function(){f.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var InputTerminalView=Backbone.View.extend({className:"terminal input-terminal",initialize:function(d){var h=d.node;var b=d.input;var c=b.name;var g=b.extensions;var a=b.multiple;var f=this.el.terminal=new InputTerminal({element:this.el,datatypes:g,multiple:a});f.node=h;f.name=c;h.input_terminals[c]=f},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.can_accept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var OutputTerminalView=Backbone.View.extend({className:"terminal output-terminal",initialize:function(c){var i=c.node;var a=c.output;var b=a.name;var h=a.extensions;var g=this.el;var f=g;var d=g.terminal=new OutputTerminal({element:g,datatypes:h});d.node=i;d.name=b;i.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes}});var InputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.multiple=a.multiple},canAccept:function(a){if(this._inputFilled()){return false}else{return this.attachable(a)}},_inputFilled:function(){return !(this.connectors.length<1||this.multiple)},attachable:function(a){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(c){var b=this;nodeView=b.nodeView;this.tool_state=c.tool_state;this.form_html=c.form_html;this.tool_errors=c.tool_errors;this.annotation=c.annotation;var d=$.parseJSON(c.post_job_actions);this.post_job_actions=d?d:{};b.nodeView.renderToolErrors();var f=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();$.each(c.data_inputs,function(h,g){b.nodeView.replaceDataInput(g,a)});f.replaceWith(a);f.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body)},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(c){var d=new InputTerminalView({node:this.node,input:c});var f=d.el;var b=new DataInputView({terminalElement:f,input:c,nodeView:this,});var a=b.$el;var f=b.terminalElement;this.$(".inputs").append(a.prepend(f))},replaceDataInput:function(c,f){var g=new InputTerminalView({node:this.node,input:c});var d=g.el;this.$("div[name='"+c.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){var h=d.terminal;if(i.handle1&&!h.attachable(i.handle1)){i.destroy()}else{h.connectors[0]=i;i.handle2=h}}});$(this).remove()});var b=new DataInputView({terminalElement:d,input:c,nodeView:this,skipResize:true,});var a=b.$el;f.append(a.prepend(d))},addDataOutput:function(a){var c=new OutputTerminalView({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(b.terminalElement))}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var d=this.nodeView.node;if(a.extensions.indexOf("input")<0){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(d.type=="tool"){var f=new OutputCalloutView({label:b,output:a,node:d,});this.$el.append(f.el);this.$el.hover(function(){f.hoverImage()},function(){f.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var InputTerminalView=Backbone.View.extend({className:"terminal input-terminal",initialize:function(d){var h=d.node;var b=d.input;var c=b.name;var g=b.extensions;var a=b.multiple;var f=this.el.terminal=new InputTerminal({element:this.el,datatypes:g,multiple:a});f.node=h;f.name=c;h.input_terminals[c]=f},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.canAccept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var OutputTerminalView=Backbone.View.extend({className:"terminal output-terminal",initialize:function(c){var i=c.node;var a=c.output;var b=a.name;var h=a.extensions;var g=this.el;var f=g;var d=g.terminal=new OutputTerminal({element:g,datatypes:h});d.node=i;d.name=b;i.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ 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
5 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bf3c4ce994bf/
Changeset: bf3c4ce994bf
User: jmchilton
Date: 2014-04-21 21:26:56
Summary: Fix comment in lib/galaxy/workflow/run.py
Affected #: 1 file
diff -r 64ae9dc170214097c419febe12e52b86bea12020 -r bf3c4ce994bf25c3744338a3d8edbdb5da847fe4 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -66,9 +66,10 @@
workflow_invocation = model.WorkflowInvocation()
workflow_invocation.workflow = self.workflow
- # Web controller will populate stateful modules on each step before calling invoke
- # but not API controller. More work should be done to further harmonize these methods
- # going forward if possible - if possible moving more web controller logic here.
+ # Web controller will populate state on each step before calling
+ # invoke but not API controller. More work should be done to further
+ # harmonize these methods going forward if possible - if possible
+ # moving more web controller logic here.
state_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "state" )
if not state_populated:
self._populate_state( )
https://bitbucket.org/galaxy/galaxy-central/commits/6d1b5997e85b/
Changeset: 6d1b5997e85b
User: jmchilton
Date: 2014-04-21 21:27:01
Summary: Workflow Editor: Rename can_accept to canAccept.
Affected #: 2 files
diff -r bf3c4ce994bf25c3744338a3d8edbdb5da847fe4 -r 6d1b5997e85b9bdb75308fdb5db6cb5fa7e09941 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -41,7 +41,7 @@
this.datatypes = attr.datatypes;
this.multiple = attr.multiple;
},
- can_accept: function ( other ) {
+ canAccept: function ( other ) {
if ( this.connectors.length < 1 || this.multiple) {
for ( var t in this.datatypes ) {
var cat_outputs = new Array();
@@ -989,7 +989,7 @@
var terminal = this.el.terminal;
// Accept a dragable if it is an output terminal and has a
// compatible type
- return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
+ return $(d.drag).hasClass( "output-terminal" ) && terminal.canAccept( d.drag.terminal );
},
onDropStart: function( e, d ) {
diff -r bf3c4ce994bf25c3744338a3d8edbdb5da847fe4 -r 6d1b5997e85b9bdb75308fdb5db6cb5fa7e09941 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -76,7 +76,7 @@
},
test_accept: function( other ) {
other = other || { node: {}, datatypes: [ "txt" ] };
- return this.input_terminal.can_accept( other );
+ return this.input_terminal.canAccept( other );
}
} );
https://bitbucket.org/galaxy/galaxy-central/commits/a1d1f25181f4/
Changeset: a1d1f25181f4
User: jmchilton
Date: 2014-04-21 21:27:01
Summary: Workflow Editor: Improve tests related to input terminal canAccept/datatypes.
Elminate stub, create mock tree off inputs (demonstrates what server is feeding), add test for direct and subtype. Add tests for PJA changing output connection datatypes.
Affected #: 1 file
diff -r 6d1b5997e85b9bdb75308fdb5db6cb5fa7e09941 -r a1d1f25181f4689de3e946ed1ce1aa5494e7d781 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -16,20 +16,25 @@
window.workflow = null;
window.canvas_manager = null;
- // Stub used over stubbing issubtype for unit testing datatype comparisons.
- var issubtypeStub = null;
QUnit.moduleStart(function() {
- if( issubtypeStub === null) {
- issubtypeStub = sinon.stub( window, "issubtype" );
- }
- });
- QUnit.moduleDone(function() {
- if( issubtypeStub !== null) {
- issubtypeStub.restore();
- issubtypeStub = null;
- }
- });
+ window.populate_datatype_info({
+ ext_to_class_name: {
+ 'txt': 'Text',
+ 'data': 'Data',
+ 'tabular': 'Tabular',
+ 'binary': 'Binary',
+ 'bam': 'Bam'
+ },
+ class_to_classes: {
+ 'Data': { 'Data': true },
+ 'Text': { 'Text': true, 'Data': true },
+ 'Tabular': { 'Tabular': true, 'Text': true, 'Data': true },
+ 'Binary': { 'Data': true, 'Binary': true },
+ 'Bam': { 'Data': true, 'Binary': true, 'Bam': true }
+ }
+ } );
+ } );
var with_canvas_container = function( f ) {
var canvas_container = $("<div id='canvas-container'>");
@@ -77,6 +82,11 @@
test_accept: function( other ) {
other = other || { node: {}, datatypes: [ "txt" ] };
return this.input_terminal.canAccept( other );
+ },
+ pja_change_datatype_node: function( output_name, newtype ) {
+ var pja = { action_type: "ChangeDatatypeAction", output_name: output_name, action_arguments: { newtype: newtype } };
+ var otherNode = { post_job_actions: [ pja ] };
+ return otherNode;
}
} );
@@ -119,18 +129,46 @@
ok( connector.destroy.called );
} );
- test( "can accept correct datatype", function() {
- issubtypeStub.returns(true);
+ test( "can accept exact datatype", function() {
+ var other = { node: {}, datatypes: [ "txt" ] }; // input also txt
+
ok( this.test_accept() ) ;
} );
- test( "cannot accept incorrect datatypes", function() {
- issubtypeStub.returns(false);
- ok( ! this.test_accept() );
+ test( "can accept subclass datatype", function() {
+ var other = { node: {}, datatypes: [ "tabular" ] }; // tabular subclass of input txt
+
+ ok( this.test_accept() ) ;
+ } );
+
+ test( "cannot accept incorrect datatype", function() {
+ var other = { node: {}, datatypes: [ "binary" ] }; // binary is not txt
+
+ ok( ! this.test_accept( other ) );
+ } );
+
+ test( "can accept incorrect datatype if converted with PJA", function() {
+ var otherNode = this.pja_change_datatype_node( "out1", "txt" );
+ var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" }; // Was binary but converted to txt
+
+ ok( this.test_accept( other ) );
+ } );
+
+ test( "cannot accept incorrect datatype if converted with PJA to incompatible type", function() {
+ var otherNode = this.pja_change_datatype_node( "out1", "bam" ); // bam's are not txt
+ var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" };
+
+ ok( ! this.test_accept( other ) );
+ } );
+
+ test( "cannot accept incorrect datatype if some other output converted with PJA to compatible type", function() {
+ var otherNode = this.pja_change_datatype_node( "out2", "txt" );
+ var other = { node: otherNode, datatypes: [ "binary" ], name: "out1" };
+
+ ok( ! this.test_accept( other ) );
} );
test( "can accept inputs", function() {
- issubtypeStub.returns(false);
// Other is data input module - always accept (currently - could be
// more intelligent by looking at what else input is connected to.
var other = { node: {}, datatypes: [ "input" ] };
@@ -138,7 +176,6 @@
} );
test( "cannot accept when already connected", function() {
- issubtypeStub.returns(true);
var self = this;
// If other is subtype but already connected, cannot accept
this.with_test_connector( {}, function() {
@@ -379,12 +416,22 @@
/* global NodeView */
module( "Node view ", {
setup: function() {
- this.set_for_node( {} );
+ this.set_for_node( { input_terminals: {}, output_terminals: {}, markChanged: function() {} } );
},
set_for_node: function( node ) {
- var element = $("<div>");
+ var element = $("<div><div class='toolFormBody'></div></div>");
this.view = new NodeView( { node: node, el: element[ 0 ] } );
},
+ connectAttachedTerminal: function( inputType, outputType ) {
+ this.view.addDataInput( { name: "TestName", extensions: [ inputType ] } );
+ var terminal = this.view.node.input_terminals[ "TestName" ];
+
+ var outputTerminal = new OutputTerminal( { name: "TestOuptut", datatypes: [ outputType ] } );
+ outputTerminal.node = { markChanged: function() {}, post_job_actions: [] };
+ var c = new Connector( outputTerminal, terminal );
+
+ return c;
+ }
} );
test( "tool error styling", function() {
@@ -413,6 +460,14 @@
} );
+ test( "replacing terminal on data input update preserves connections", function() {
+ var connector = this.connectAttachedTerminal( "txt", "txt" );
+ var newElement = $("<div class='inputs'></div>");
+ this.view.replaceDataInput( { name: "TestName", extensions: ["txt"] }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector.handle2 === terminal );
+ } );
+
/* global InputTerminalView */
module( "Input terminal view", {
setup: function() {
https://bitbucket.org/galaxy/galaxy-central/commits/69a77f2783fc/
Changeset: 69a77f2783fc
User: jmchilton
Date: 2014-04-21 21:27:01
Summary: Workflow Editor: Break canAccept into smaller pieces (inputFilled and attachable).
Want to reuse attachable right away to fix a bug - and the smaller pieces are good refactoring to support different kinds of input types in dataset collections downstream.
Affected #: 1 file
diff -r a1d1f25181f4689de3e946ed1ce1aa5494e7d781 -r 69a77f2783fcd9317f1da329c3f7a5512762ce99 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -42,23 +42,31 @@
this.multiple = attr.multiple;
},
canAccept: function ( other ) {
- if ( this.connectors.length < 1 || this.multiple) {
- for ( var t in this.datatypes ) {
- var cat_outputs = new Array();
- cat_outputs = cat_outputs.concat(other.datatypes);
- if (other.node.post_job_actions){
- for (var pja_i in other.node.post_job_actions){
- var pja = other.node.post_job_actions[pja_i];
- if (pja.action_type == "ChangeDatatypeAction" && (pja.output_name == '' || pja.output_name == other.name) && pja.action_arguments){
- cat_outputs.push(pja.action_arguments['newtype']);
- }
+ if( this._inputFilled() ) {
+ return false;
+ } else {
+ return this.attachable( other );
+ }
+ },
+ _inputFilled: function( ) {
+ return ! ( this.connectors.length < 1 || this.multiple );
+ },
+ attachable: function( other ) {
+ for ( var t in this.datatypes ) {
+ var cat_outputs = new Array();
+ cat_outputs = cat_outputs.concat(other.datatypes);
+ if (other.node.post_job_actions){
+ for (var pja_i in other.node.post_job_actions){
+ var pja = other.node.post_job_actions[pja_i];
+ if (pja.action_type == "ChangeDatatypeAction" && (pja.output_name == '' || pja.output_name == other.name) && pja.action_arguments){
+ cat_outputs.push(pja.action_arguments['newtype']);
}
}
- // FIXME: No idea what to do about case when datatype is 'input'
- for ( var other_datatype_i in cat_outputs ) {
- if ( cat_outputs[other_datatype_i] == "input" || issubtype( cat_outputs[other_datatype_i], this.datatypes[t] ) ) {
- return true;
- }
+ }
+ // FIXME: No idea what to do about case when datatype is 'input'
+ for ( var other_datatype_i in cat_outputs ) {
+ if ( cat_outputs[other_datatype_i] == "input" || issubtype( cat_outputs[other_datatype_i], this.datatypes[t] ) ) {
+ return true;
}
}
}
https://bitbucket.org/galaxy/galaxy-central/commits/4df5e43d8651/
Changeset: 4df5e43d8651
User: jmchilton
Date: 2014-04-21 21:27:01
Summary: Bugfix: Workflow editor could get in invalid state when trying to preserve connections.
Workflow editor would preserve connections when a tool would update its state (for instance switching a conditional or adding repeat) - but conditional switching can result in connections being invalid (wouldn't have passed can_accept previously). Consider the following tool for instance which changes datatypes of an input based on a conditional (https://gist.github.com/jmchilton/11152628)
Affected #: 2 files
diff -r 69a77f2783fcd9317f1da329c3f7a5512762ce99 -r 4df5e43d865176cdeb929db7fbf18c3b9af98591 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -806,8 +806,14 @@
$(this).find( ".input-terminal" ).each( function() {
var c = this.terminal.connectors[0];
if ( c ) {
- t.terminal.connectors[0] = c;
- c.handle2 = t.terminal;
+ var terminal = t.terminal;
+ if( c.handle1 && ! terminal.attachable( c.handle1 ) ) {
+ // connection no longer valid, destroy it
+ c.destroy();
+ } else {
+ terminal.connectors[0] = c;
+ c.handle2 = terminal;
+ }
}
});
$(this).remove();
diff -r 69a77f2783fcd9317f1da329c3f7a5512762ce99 -r 4df5e43d865176cdeb929db7fbf18c3b9af98591 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -468,6 +468,16 @@
ok( connector.handle2 === terminal );
} );
+ test( "replacing terminal on data input destroys invalid connections", function() {
+ var connector = this.connectAttachedTerminal( "txt", "txt" );
+ var newElement = $("<div class='inputs'></div>");
+ var connector_destroy_spy = sinon.spy( connector, "destroy" );
+ // Replacing input with same name - but now of type bam should destroy connection.
+ this.view.replaceDataInput( { name: "TestName", extensions: ["bam"] }, newElement );
+ var terminal = newElement.find(".input-terminal")[ 0 ].terminal;
+ ok( connector_destroy_spy.called );
+ } );
+
/* global InputTerminalView */
module( "Input terminal view", {
setup: function() {
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Client app: use in /base.mako, rework app init to use AMD definition
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/64ae9dc17021/
Changeset: 64ae9dc17021
User: carlfeberhard
Date: 2014-04-21 20:44:34
Summary: Client app: use in /base.mako, rework app init to use AMD definition
Affected #: 5 files
diff -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 -r 64ae9dc170214097c419febe12e52b86bea12020 templates/base.mako
--- a/templates/base.mako
+++ b/templates/base.mako
@@ -1,3 +1,6 @@
+<%namespace name="galaxy_client" file="/galaxy_client_app.mako" />
+<% self.js_app = None %>
+
<% _=n_ %><!DOCTYPE HTML><html>
@@ -80,6 +83,8 @@
});
</script>
+ ${ galaxy_client.load( app=self.js_app ) }
+
%if not form_input_auto_focus is UNDEFINED and form_input_auto_focus:
<script type="text/javascript">
$(document).ready( function() {
diff -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 -r 64ae9dc170214097c419febe12e52b86bea12020 templates/base/base_panels.mako
--- a/templates/base/base_panels.mako
+++ b/templates/base/base_panels.mako
@@ -60,8 +60,6 @@
"mvc/ui"
)}
- ${ galaxy_client.load() }
-
<script type="text/javascript">
## global configuration object
var galaxy_config =
@@ -92,6 +90,10 @@
}
});
</script>
+
+ ## load the Galaxy global js var
+ ${ galaxy_client.load() }
+
</%def>
## Default late-load javascripts
diff -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 -r 64ae9dc170214097c419febe12e52b86bea12020 templates/galaxy_client_app.mako
--- a/templates/galaxy_client_app.mako
+++ b/templates/galaxy_client_app.mako
@@ -1,8 +1,10 @@
## ============================================================================
<%def name="bootstrap( **kwargs )">
- ## Bootstap dictionaries for GalaxyApp object's JSON, create GalaxyApp,
- ## and steal existing attributes from plain objects already created
+ ## 1) Bootstap all kwargs to json, assigning to:
+ ## global 'bootstrapped' var
+ ## named require module 'bootstrapped-data'
+ ## 2) and automatically include json for config and user in bootstapped data
<%
kwargs.update({
'config' : get_config_dict(),
@@ -10,6 +12,7 @@
})
%><script type="text/javascript">
+ //TODO: global...
%for key in kwargs:
( window.bootstrapped = window.bootstrapped || {} )[ '${key}' ] = (
${ h.to_json_string( kwargs[ key ], indent=( 2 if trans.debug else 0 ) )} );
@@ -20,7 +23,8 @@
</script></%def>
-<%def name="load( init_fn=None, **kwargs )">
+<%def name="load( app=None, **kwargs )">
+ ## 1) bootstrap kwargs (as above), 2) build Galaxy global var, 3) load 'app' by AMD (optional)
${ self.bootstrap( **kwargs ) }
<script type="text/javascript">
require([ 'require', 'galaxy-app-base' ], function( require, galaxy ){
@@ -31,10 +35,9 @@
loggerOptions : {}
});
- var initFn = ${ 'window[ "%s" ]' %( init_fn ) if init_fn else 'undefined' };
- if( typeof initFn === 'function' ){
- initFn();
- }
+ %if app:
+ require([ '${app}' ]);
+ %endif
});
</script></%def>
diff -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 -r 64ae9dc170214097c419febe12e52b86bea12020 templates/webapps/galaxy/galaxy.panels.mako
--- a/templates/webapps/galaxy/galaxy.panels.mako
+++ b/templates/webapps/galaxy/galaxy.panels.mako
@@ -55,9 +55,6 @@
## make sure console exists
<script type="text/javascript">
- // start a Galaxy namespace for objects created
- window.Galaxy = window.Galaxy || {};
-
// console protection
window.console = window.console ||
{
@@ -91,7 +88,6 @@
%endif
</style>
-
## default script wrapper
<script type="text/javascript">
## configure require
@@ -103,25 +99,33 @@
"libs/backbone/backbone": { exports: "Backbone" },
}
});
+ var galaxy_config = ${ h.to_json_string( self.galaxy_config ) };
// load any app configured
- var galaxy_config = ${ h.to_json_string( self.galaxy_config ) };
- window.init = function(){
+ define( 'app', function(){
var jscript = galaxy_config.app.jscript;
if( jscript ){
require([ jscript ], function( js_lib ){
$( function(){
- ## load galaxy module application
+ // load galaxy module application
var module = new js_lib.GalaxyApp();
});
});
} else {
console.log("'galaxy_config.app.jscript' missing.");
}
- }
+ });
</script>
- ${ galaxy_client.load( init_fn='init' ) }
+ ## load the Galaxy global js var and run 'app' from above
+ ${ galaxy_client.load( app='app' ) }
+
+ ## alternate call where the module calls itself when included (no call to GalaxyApp()) - the above won't be needed
+ ##precondition: module must call jq onready itself
+ ##<% app_config = self.galaxy_config[ 'app' ]; print app_config %>
+ ##${ galaxy_client.load( app=( app_config[ 'jscript' ] if 'jscript' in app_config else None )) }
+ ##TODO: at that point, we can think about optimizing the various apps
+
</%def>
## default late-load javascripts
diff -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 -r 64ae9dc170214097c419febe12e52b86bea12020 templates/webapps/galaxy/root/history.mako
--- a/templates/webapps/galaxy/root/history.mako
+++ b/templates/webapps/galaxy/root/history.mako
@@ -6,26 +6,16 @@
</%def>
## -----------------------------------------------------------------------------
-<%def name="stylesheets()">
- ${ parent.stylesheets() }
- <style>
- body.historyPage {
- margin: 0px;
- padding: 0px;
- }
- </style>
-</%def>
-
-## -----------------------------------------------------------------------------
<%def name="javascripts()">
${ parent.javascripts() }
<script type="text/javascript">
$(function(){
- $( 'body' ).addClass( 'historyPage' ).addClass( 'history-panel' );
+ $( 'body' ).addClass( 'historyPage' ).addClass( 'history-panel' )
+ .css({ margin: '0px', padding: '0px' });
});
-window.app = function(){
+define( 'app', function(){
require([
'mvc/history/current-history-panel'
], function( historyPanel ){
@@ -38,13 +28,13 @@
el : $( "body" ),
model : new historyModel.History( bootstrapped.history, bootstrapped.hdas ),
onready : function(){
- this.render( 0 );
+ this.render();
}
});
});
});
-}
+})
</script>
-${ galaxy_client.load( 'app', history=history, hdas=hdas, show_deleted=show_deleted, show_hidden=show_hidden ) }
+${ galaxy_client.load( app='app', history=history, hdas=hdas, show_deleted=show_deleted, show_hidden=show_hidden ) }
</%def>
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: davebgx: Fix for registering an account with custom user information when only one custom user info form is defined. Fix editing user info when custom user info forms are defined. Fix functional tests for user info.
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/a247bdaecba9/
Changeset: a247bdaecba9
User: davebgx
Date: 2014-04-21 18:41:05
Summary: Fix for registering an account with custom user information when only one custom user info form is defined. Fix editing user info when custom user info forms are defined. Fix functional tests for user info.
Affected #: 5 files
diff -r 990979ee295e919be24b112a7cad215641c729ad -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -623,7 +623,6 @@
@web.expose
def create( self, trans, cntrller='user', redirect_url='', refresh_frames=[], **kwd ):
params = util.Params( kwd )
-
# If the honeypot field is not empty we are dealing with a bot.
honeypot_field = params.get( 'bear_field', '' )
if honeypot_field != '':
@@ -927,6 +926,7 @@
user_type_fd_id_select_field=user_type_fd_id_select_field,
user_info_forms=user_info_forms,
user_type_form_definition=user_type_form_definition,
+ user_type_fd_id=user_type_fd_id,
widgets=widgets,
addresses=addresses,
show_filter=show_filter,
diff -r 990979ee295e919be24b112a7cad215641c729ad -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 templates/user/register.mako
--- a/templates/user/register.mako
+++ b/templates/user/register.mako
@@ -139,7 +139,7 @@
all Galaxy project mailing lists</a>.</p></div>
%endif
- %if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) > 1:
+ %if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) >= 1:
<div class="form-row"><label>User type</label>
${user_type_fd_id_select_field.get_html()}
diff -r 990979ee295e919be24b112a7cad215641c729ad -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 templates/webapps/galaxy/user/manage_info.mako
--- a/templates/webapps/galaxy/user/manage_info.mako
+++ b/templates/webapps/galaxy/user/manage_info.mako
@@ -13,13 +13,13 @@
<div class="toolForm"><form name="user_info" id="user_info" action="${h.url_for( controller='user', action='edit_info', cntrller=cntrller, user_id=trans.security.encode_id( user.id ) )}" method="post" ><div class="toolFormTitle">User information</div>
- %if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) > 1:
+ %if user_type_fd_id_select_field and len( user_type_fd_id_select_field.options ) >= 1:
<div class="form-row"><label>User type:</label>
${user_type_fd_id_select_field.get_html()}
</div>
%else:
- <input type="hidden" name="user_type_fd_id" value="${trans.security.encode_id( user_type_form_definition.id )}"/>
+ <input type="hidden" name="user_type_fd_id" value="${trans.security.encode_id( user_type_fd_id )}"/>
%endif
%for field in widgets:
<div class="form-row">
diff -r 990979ee295e919be24b112a7cad215641c729ad -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 test/base/twilltestcase.py
--- a/test/base/twilltestcase.py
+++ b/test/base/twilltestcase.py
@@ -1039,17 +1039,17 @@
strings_displayed=[], strings_displayed_after_submit=[] ):
# This method creates a new user with associated info
self.visit_url( "%s/user/create?cntrller=%s&use_panels=False" % ( self.url, cntrller ) )
- tc.fv( "1", "email", email )
- tc.fv( "1", "password", password )
- tc.fv( "1", "confirm", password )
- tc.fv( "1", "username", username )
+ tc.fv( "registration", "email", email )
+ tc.fv( "registration", "password", password )
+ tc.fv( "registration", "confirm", password )
+ tc.fv( "registration", "username", username )
if user_type_fd_id:
# The user_type_fd_id SelectField requires a refresh_on_change
- self.refresh_form( 'user_type_fd_id', user_type_fd_id )
- tc.fv( "1", "password", password )
- tc.fv( "1", "confirm", password )
+ self.refresh_form( 'user_type_fd_id', user_type_fd_id, form_id='registration' )
+ tc.fv( "registration", "password", password )
+ tc.fv( "registration", "confirm", password )
for index, ( field_name, info_value ) in enumerate( user_info_values ):
- tc.fv( "1", field_name, info_value )
+ tc.fv( "registration", field_name, info_value )
for check_str in strings_displayed:
self.check_page_for_string( check_str)
tc.submit( "create_user_button" )
@@ -1345,12 +1345,12 @@
pass
tc.submit( button )
- def refresh_form( self, control_name, value, form_no=0, **kwd ):
+ def refresh_form( self, control_name, value, form_no=0, form_id=None, **kwd ):
"""Handles Galaxy's refresh_on_change for forms without ultimately submitting the form"""
# control_name is the name of the form field that requires refresh_on_change, and value is
# the value to which that field is being set.
for i, f in enumerate( self.showforms() ):
- if i == form_no:
+ if i == form_no or ( form_id is not None and f.id == form_id ):
break
try:
control = f.find_control( name=control_name )
@@ -1684,6 +1684,7 @@
num_fields=1, num_options=0, field_name='1_field_name', strings_displayed=[],
strings_displayed_after_submit=[] ):
"""Create a new form definition."""
+ strings_displayed_after_submit.extend( [ name, description, form_type ] )
self.visit_url( "%s/forms/create_form_definition" % self.url )
for check_str in strings_displayed:
self.check_page_for_string( check_str )
diff -r 990979ee295e919be24b112a7cad215641c729ad -r a247bdaecba956f1a1b74713ba7fd9ec100e0342 test/functional/test_user_info.py
--- a/test/functional/test_user_info.py
+++ b/test/functional/test_user_info.py
@@ -1,9 +1,8 @@
from base.twilltestcase import *
from base.test_db_util import *
+class TestUserInfo( TwillTestCase ):
-# TODO: Functional tests start failing at 020, fix or eliminate rest of tests.
-class TestUserInfo( TwillTestCase ):
def test_000_initiate_users( self ):
"""Ensuring all required user accounts exist"""
self.logout()
@@ -34,91 +33,65 @@
assert admin_user is not None, 'Problem retrieving user with email "test(a)bx.psu.edu" from the database'
global admin_user_private_role
admin_user_private_role = get_private_role( admin_user )
+
def test_005_create_user_info_forms( self ):
"""Testing creating a new user info form and editing it"""
# Logged in as admin_user
# Create a the first form
- name = "Student"
- desc = "This is Student user info form's description"
- form_type = get_user_info_form_definition()
- self.create_form( name=name,
- description=desc,
- form_type=form_type,
+ self.create_form( name='Student',
+ description="This is Student user info form's description",
+ form_type=get_user_info_form_definition(),
num_fields=0,
strings_displayed=[ 'Create a new form definition' ],
- strings_displayed_after_submit=[ name, desc, form_type ] )
- tmp_form = get_form( name )
- # field names
- global affiliation_field_name
- affiliation_field_name = 'affiliation'
- global organization_field_name
- organization_field_name = 'name_of_organization'
- global feedback_field_name
- feedback_field_name = 'contact_for_feedback'
+ strings_displayed_after_submit=[] )
+ tmp_form = get_form( 'Student' )
# Add fields to the form
field_dicts = [ dict( label='Affiliation',
desc='The type of organization you are affiliated with',
type='SelectField',
required='optional',
selectlist=[ 'Educational', 'Research', 'Commercial' ],
- name=affiliation_field_name ),
+ name='affiliation' ),
dict( label='Name of Organization',
desc='',
type='TextField',
required='optional',
- name=organization_field_name ),
+ name='name_of_oganization' ),
dict( label='Contact for feedback',
desc='',
type='CheckboxField',
required='optional',
- name=feedback_field_name ) ]
+ name='contact_for_feedback' ) ]
self.edit_form( id=self.security.encode_id( tmp_form.current.id ),
field_dicts=field_dicts,
field_index=len( tmp_form.fields ),
- strings_displayed=[ 'Edit form definition "%s"' % name ],
- strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % name ] )
+ strings_displayed=[ 'Edit form definition "Student"' ],
+ strings_displayed_after_submit=[ "The form 'Student' has been updated with the changes." ] )
# Get the form_definition object for later tests
global form_one
- form_one = get_form( name )
- assert form_one is not None, 'Problem retrieving form named "%s" from the database' % name
+ form_one = get_form( 'Student' )
+ assert form_one is not None, 'Problem retrieving form named "Student" from the database'
assert len( form_one.fields ) == len( tmp_form.fields ) + len( field_dicts )
# Create the second form
- name = "Researcher"
- desc = "This is Researcher user info form's description"
- self.create_form( name=name,
- description=desc,
- form_type=form_type,
+ self.create_form( name='Researcher',
+ description="This is Researcher user info form's description",
+ form_type=get_user_info_form_definition(),
num_fields=0,
strings_displayed=[ 'Create a new form definition' ],
- strings_displayed_after_submit=[ name, desc, form_type ] )
- tmp_form = get_form( name )
+ strings_displayed_after_submit=[] )
+ tmp_form = get_form( 'Researcher' )
# Add fields to the form
- field_dicts = [ dict( label='Affiliation',
- desc='The type of organization you are affiliated with',
- type='SelectField',
- required='optional',
- selectlist=[ 'Educational', 'Research', 'Commercial' ],
- name=affiliation_field_name ),
- dict( label='Name of Organization',
- desc='',
- type='TextField',
- required='optional',
- name=organization_field_name ),
- dict( label='Contact for feedback',
- desc='',
- type='CheckboxField',
- required='optional',
- name=feedback_field_name ) ]
self.edit_form( id=self.security.encode_id( tmp_form.current.id ),
field_dicts=field_dicts,
field_index=len( tmp_form.fields ),
- strings_displayed=[ 'Edit form definition "%s"' % name ],
- strings_displayed_after_submit=[ "The form '%s' has been updated with the changes." % name ] )
+ strings_displayed=[ 'Edit form definition "Researcher"' ],
+ strings_displayed_after_submit=[ "The form 'Researcher' has been updated with the changes." ] )
# Get the form_definition object for later tests
global form_two
- form_two = get_form( name )
- assert form_two is not None, 'Problem retrieving form named "%s" from the database' % name
+ form_two = get_form( 'Researcher' )
+ assert form_two is not None, 'Problem retrieving form named "Researcher" from the database'
assert len( form_two.fields ) == len( tmp_form.fields ) + len( field_dicts )
+
def test_010_user_reqistration_multiple_user_info_forms( self ):
"""Testing user registration with multiple user info forms"""
# Logged in as admin_user
@@ -129,9 +102,9 @@
email = 'test11(a)bx.psu.edu'
password = 'testuser'
username = 'test11'
- user_info_values=[ ( affiliation_field_name, 'Educational' ),
- ( organization_field_name, 'Penn State' ),
- ( feedback_field_name, '1' ) ]
+ user_info_values=[ ( 'affiliation', 'Educational' ),
+ ( 'name_of_oganization', 'Penn State' ),
+ ( 'contact_for_feedback', '1' ) ]
self.create_user_with_info( cntrller='admin',
email=email,
password=password,
@@ -147,12 +120,13 @@
self.logout()
self.login( email=regular_user11.email, username=username )
global form_checkbox_field3_string
- form_checkbox_field3_string = '<input type="checkbox" id="%s" name="%s" value="true" checked="checked">' % ( feedback_field_name, feedback_field_name )
+ form_checkbox_field3_string = '<input type="checkbox" id="contact_for_feedback" name="contact_for_feedback" value="true" checked="checked">'
self.edit_user_info( cntrller='user',
strings_displayed=[ "Manage User Information",
user_info_values[0][1],
user_info_values[1][1],
form_checkbox_field3_string ] )
+
def test_015_user_reqistration_single_user_info_forms( self ):
"""Testing user registration with a single user info form"""
# Logged in as regular_user_11
@@ -166,9 +140,9 @@
email = 'test12(a)bx.psu.edu'
password = 'testuser'
username = 'test12'
- user_info_values=[ ( affiliation_field_name, 'Educational' ),
- ( organization_field_name, 'Penn State' ),
- ( feedback_field_name, '1' ) ]
+ user_info_values=[ ( 'affiliation', 'Educational' ),
+ ( 'name_of_oganization', 'Penn State' ),
+ ( 'contact_for_feedback', '1' ) ]
self.create_user_with_info( cntrller='admin',
email=email,
password=password,
@@ -188,10 +162,12 @@
user_info_values[0][1],
user_info_values[1][1],
form_checkbox_field3_string ] )
+
def test_020_edit_user_info( self ):
"""Testing editing user info as a regular user"""
# Logged in as regular_user_12
# Test changing email and user name - first try an invalid user name
+ regular_user12 = get_user( 'test12(a)bx.psu.edu' )
self.edit_user_info( cntrller='user',
new_email='test12_new(a)bx.psu.edu',
new_username='test12_new',
@@ -214,11 +190,12 @@
# Test logging in with new email and password
self.login( email=regular_user12.email, password='testuser#' )
# Test editing the user info
- new_user_info_values=[ ( affiliation_field_name, 'Educational' ),
- ( organization_field_name, 'Penn State' ) ]
+ new_user_info_values=[ ( 'affiliation', 'Educational' ),
+ ( 'name_of_oganization', 'Penn State' ) ]
self.edit_user_info( cntrller='user',
info_values=new_user_info_values,
strings_displayed_after_submit=[ "The user information has been updated with the changes" ] )
+
def test_999_reset_data_for_later_test_runs( self ):
"""Reseting data to enable later test runs to pass"""
# Logged in as regular_user_12
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Fix for masthead link for biostar mainpage.
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/990979ee295e/
Changeset: 990979ee295e
User: dan
Date: 2014-04-21 18:12:03
Summary: Fix for masthead link for biostar mainpage.
Affected #: 3 files
diff -r 5d4d8c336e6d9d74865a8e5009fd5ccdbd99e94e -r 990979ee295e919be24b112a7cad215641c729ad static/scripts/galaxy.menu.js
--- a/static/scripts/galaxy.menu.js
+++ b/static/scripts/galaxy.menu.js
@@ -196,7 +196,7 @@
{
tab_help.add({
title : "Galaxy Q&A Site",
- content : this.options.biostar_url,
+ content : this.options.biostar_url_redirect,
target : "_blank"
});
tab_help.add({
diff -r 5d4d8c336e6d9d74865a8e5009fd5ccdbd99e94e -r 990979ee295e919be24b112a7cad215641c729ad static/scripts/packed/galaxy.menu.js
--- a/static/scripts/packed/galaxy.menu.js
+++ b/static/scripts/packed/galaxy.menu.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var e=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Analysis home view"});this.masthead.append(e);var g={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){g.disabled=true}var d=new b.GalaxyMastheadTab(g);this.masthead.append(d);var i=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access published resources"});i.add({title:"Data Libraries",content:"library/index"});i.add({title:"Data Libraries Beta",content:"library/list",divider:true});i.add({title:"Published Histories",content:"history/list_published"});i.add({title:"Published Workflows",content:"workflow/list_published"});i.add({title:"Published Visualizations",content:"visualization/list_published"});i.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(i);if(this.options.user.requests){var j=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});j.add({title:"Sequencing Requests",content:"requests/index"});j.add({title:"Find Samples",content:"requests/find_samples_index"});j.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(j)}var c={id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize datasets"};if(!this.options.user.valid){c.disabled=true}var m=new b.GalaxyMastheadTab(c);if(this.options.user.valid){m.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});m.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"})}this.masthead.append(m);if(this.options.enable_cloud_launch){var f=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});f.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(f)}if(this.options.is_admin_user){var h=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(h)}var l=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Support, contact, and community hubs"});if(this.options.biostar_url){l.add({title:"Galaxy Q&A Site",content:this.options.biostar_url,target:"_blank"});l.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}l.add({title:"Support",content:this.options.support_url,target:"_blank"});l.add({title:"Search",content:this.options.search_url,target:"_blank"});l.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});l.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});l.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});l.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(this.options.terms_url){l.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(l);if(!this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account registration or login"});k.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){k.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(k)}else{var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account preferences and saved data"});k.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){k.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{k.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});k.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});k.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}k.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});k.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});k.add({title:"Saved Pages",content:"page/list",target:"_top"});k.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){k.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(k)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
+define(["galaxy.masthead"],function(b){var a=Backbone.Model.extend({options:null,masthead:null,initialize:function(c){this.options=c.config;this.masthead=c.masthead;this.create()},create:function(){var e=new b.GalaxyMastheadTab({id:"analysis",title:"Analyze Data",content:"root/index",title_attribute:"Analysis home view"});this.masthead.append(e);var g={id:"workflow",title:"Workflow",content:"workflow",title_attribute:"Chain tools into workflows"};if(!this.options.user.valid){g.disabled=true}var d=new b.GalaxyMastheadTab(g);this.masthead.append(d);var i=new b.GalaxyMastheadTab({id:"shared",title:"Shared Data",content:"library/index",title_attribute:"Access published resources"});i.add({title:"Data Libraries",content:"library/index"});i.add({title:"Data Libraries Beta",content:"library/list",divider:true});i.add({title:"Published Histories",content:"history/list_published"});i.add({title:"Published Workflows",content:"workflow/list_published"});i.add({title:"Published Visualizations",content:"visualization/list_published"});i.add({title:"Published Pages",content:"page/list_published"});this.masthead.append(i);if(this.options.user.requests){var j=new b.GalaxyMastheadTab({id:"lab",title:"Lab"});j.add({title:"Sequencing Requests",content:"requests/index"});j.add({title:"Find Samples",content:"requests/find_samples_index"});j.add({title:"Help",content:this.options.lims_doc_url});this.masthead.append(j)}var c={id:"visualization",title:"Visualization",content:"visualization/list",title_attribute:"Visualize datasets"};if(!this.options.user.valid){c.disabled=true}var m=new b.GalaxyMastheadTab(c);if(this.options.user.valid){m.add({title:"New Track Browser",content:"visualization/trackster",target:"_frame"});m.add({title:"Saved Visualizations",content:"visualization/list",target:"_frame"})}this.masthead.append(m);if(this.options.enable_cloud_launch){var f=new b.GalaxyMastheadTab({id:"cloud",title:"Cloud",content:"cloudlaunch/index"});f.add({title:"New Cloud Cluster",content:"cloudlaunch/index"});this.masthead.append(f)}if(this.options.is_admin_user){var h=new b.GalaxyMastheadTab({id:"admin",title:"Admin",content:"admin/index",extra_class:"admin-only",title_attribute:"Administer this Galaxy"});this.masthead.append(h)}var l=new b.GalaxyMastheadTab({id:"help",title:"Help",title_attribute:"Support, contact, and community hubs"});if(this.options.biostar_url){l.add({title:"Galaxy Q&A Site",content:this.options.biostar_url_redirect,target:"_blank"});l.add({title:"Ask a question",content:"biostar/biostar_question_redirect",target:"_blank"})}l.add({title:"Support",content:this.options.support_url,target:"_blank"});l.add({title:"Search",content:this.options.search_url,target:"_blank"});l.add({title:"Mailing Lists",content:this.options.mailing_lists,target:"_blank"});l.add({title:"Videos",content:this.options.screencasts_url,target:"_blank"});l.add({title:"Wiki",content:this.options.wiki_url,target:"_blank"});l.add({title:"How to Cite Galaxy",content:this.options.citation_url,target:"_blank"});if(this.options.terms_url){l.add({title:"Terms and Conditions",content:this.options.terms_url,target:"_blank"})}this.masthead.append(l);if(!this.options.user.valid){var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedout-only",title_attribute:"Account registration or login"});k.add({title:"Login",content:"user/login",target:"galaxy_main"});if(this.options.allow_user_creation){k.add({title:"Register",content:"user/create",target:"galaxy_main"})}this.masthead.append(k)}else{var k=new b.GalaxyMastheadTab({id:"user",title:"User",extra_class:"loggedin-only",title_attribute:"Account preferences and saved data"});k.add({title:"Logged in as "+this.options.user.email});if(this.options.use_remote_user&&this.options.remote_user_logout_href){k.add({title:"Logout",content:this.options.remote_user_logout_href,target:"_top"})}else{k.add({title:"Preferences",content:"user?cntrller=user",target:"galaxy_main"});k.add({title:"Custom Builds",content:"user/dbkeys",target:"galaxy_main"});k.add({title:"Logout",content:"user/logout",target:"_top",divider:true})}k.add({title:"Saved Histories",content:"history/list",target:"galaxy_main"});k.add({title:"Saved Datasets",content:"dataset/list",target:"galaxy_main"});k.add({title:"Saved Pages",content:"page/list",target:"_top"});k.add({title:"API Keys",content:"user/api_keys?cntrller=user",target:"galaxy_main"});if(this.options.use_remote_user){k.add({title:"Public Name",content:"user/edit_username?cntrller=user",target:"galaxy_main"})}this.masthead.append(k)}if(this.options.active_view){this.masthead.highlight(this.options.active_view)}}});return{GalaxyMenu:a}});
\ No newline at end of file
diff -r 5d4d8c336e6d9d74865a8e5009fd5ccdbd99e94e -r 990979ee295e919be24b112a7cad215641c729ad templates/webapps/galaxy/galaxy.masthead.mako
--- a/templates/webapps/galaxy/galaxy.masthead.mako
+++ b/templates/webapps/galaxy/galaxy.masthead.mako
@@ -41,6 +41,7 @@
'enable_cloud_launch' : app.config.get_bool('enable_cloud_launch', False),
'lims_doc_url' : app.config.get("lims_doc_url", "http://main.g2.bx.psu.edu/u/rkchak/p/sts"),
'biostar_url' : app.config.biostar_url,
+ 'biostar_url_redirect' : h.url_for( controller='biostar', action='biostar_redirect', qualified=True ),
'support_url' : app.config.get("support_url", "http://wiki.galaxyproject.org/Support"),
'search_url' : app.config.get("search_url", "http://galaxyproject.org/search/usegalaxy/"),
'mailing_lists' : app.config.get("mailing_lists", "http://wiki.galaxyproject.org/MailingLists"),
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Prevent redirect misuse on user log in.
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/5d4d8c336e6d/
Changeset: 5d4d8c336e6d
User: dan
Date: 2014-04-21 18:11:49
Summary: Prevent redirect misuse on user log in.
Affected #: 2 files
diff -r 6f8070735e6f36fd1cd7b79d7cef1d69ebf8c1d6 -r 5d4d8c336e6d9d74865a8e5009fd5ccdbd99e94e lib/galaxy/util/__init__.py
--- a/lib/galaxy/util/__init__.py
+++ b/lib/galaxy/util/__init__.py
@@ -29,6 +29,8 @@
from hashlib import md5
from itertools import izip
+from urlparse import urlparse
+
from galaxy import eggs
eggs.require( 'docutils' )
@@ -691,6 +693,17 @@
def string_to_object( s ):
return pickle.loads( binascii.unhexlify( s ) )
+def compare_urls( url1, url2, compare_scheme=True, compare_hostname=True, compare_path=True ):
+ url1 = urlparse( url1 )
+ url2 = urlparse( url2 )
+ if compare_scheme and url1.scheme and url2.scheme and url1.scheme != url2.scheme:
+ return False
+ if compare_hostname and url1.hostname and url2.hostname and url1.hostname != url2.hostname:
+ return False
+ if compare_path and url1.path and url2.path and url1.path != url2.path:
+ return False
+ return True
+
def get_ucsc_by_build(build):
sites = []
for site in ucsc_build_sites:
diff -r 6f8070735e6f36fd1cd7b79d7cef1d69ebf8c1d6 -r 5d4d8c336e6d9d74865a8e5009fd5ccdbd99e94e lib/galaxy/webapps/galaxy/controllers/user.py
--- a/lib/galaxy/webapps/galaxy/controllers/user.py
+++ b/lib/galaxy/webapps/galaxy/controllers/user.py
@@ -445,26 +445,35 @@
return self.user_openid_grid( trans, **kwd )
@web.expose
- def login( self, trans, redirect_url='', refresh_frames=[], **kwd ):
+ def login( self, trans, refresh_frames=[], **kwd ):
'''Handle Galaxy Log in'''
redirect = kwd.get( 'redirect', trans.request.referer ).strip()
+ root_url = url_for( '/', qualified=True )
+ redirect_url = '' #always start with redirect_url being empty
+ # compare urls, to prevent a redirect from pointing (directly) outside of galaxy
+ # or to enter a logout/login loop
+ if not util.compare_urls( root_url, redirect, compare_path=False ) or util.compare_urls( url_for( controller='user', action='logout', qualified=True ), redirect ):
+ redirect = root_url
use_panels = util.string_as_bool( kwd.get( 'use_panels', False ) )
message = kwd.get( 'message', '' )
status = kwd.get( 'status', 'done' )
header = ''
- user = None
+ user = trans.user
email = kwd.get( 'email', '' )
- if kwd.get( 'login_button', False ):
+ if user:
+ #already logged in
+ redirect_url = redirect
+ message = 'You are already logged in.'
+ status = 'info'
+ elif kwd.get( 'login_button', False ):
if trans.webapp.name == 'galaxy' and not refresh_frames:
if trans.app.config.require_login:
refresh_frames = [ 'masthead', 'history', 'tools' ]
else:
refresh_frames = [ 'masthead', 'history' ]
message, status, user, success = self.__validate_login( trans, **kwd )
- if success and redirect and not redirect.startswith( trans.request.base + url_for( controller='user', action='logout' ) ):
+ if success:
redirect_url = redirect
- elif success:
- redirect_url = url_for( '/' )
if not user and trans.app.config.require_login:
if trans.app.config.allow_user_creation:
create_account_str = " If you don't already have an account, <a href='%s'>you may create one</a>." % \
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Metrics: make the cache use localStorage for persistence
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6f8070735e6f/
Changeset: 6f8070735e6f
User: carlfeberhard
Date: 2014-04-21 17:37:26
Summary: Metrics: make the cache use localStorage for persistence
Affected #: 3 files
diff -r f1c9df0b5cabb998dd82dc6a154f66677173ffb8 -r 6f8070735e6f36fd1cd7b79d7cef1d69ebf8c1d6 static/scripts/packed/utils/metrics-logger.js
--- a/static/scripts/packed/utils/metrics-logger.js
+++ b/static/scripts/packed/utils/metrics-logger.js
@@ -1,1 +1,1 @@
-define([],function(){function h(z){z=z||{};var y=this;y.userId=window.bootstrapped?window.bootstrapped.user.id:null;y.userId=y.userId||z.userId||null;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){y._emitToConsole("warn","MetricsLogger",["Metrics logger could not stringify logArguments:",A,z]);y._emitToConsole("error","MetricsLogger",[B])}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}});
\ No newline at end of file
+define([],function(){function i(D){D=D||{};var C=this;C.userId=window.bootstrapped?window.bootstrapped.user.id:null;C.userId=C.userId||D.userId||null;C.consoleLogger=D.consoleLogger||null;C._init(D);return C}i.ALL=0;i.DEBUG=10;i.INFO=20;i.WARN=30;i.ERROR=40;i.METRIC=50;i.NONE=100;i.defaultOptions={logLevel:i.NONE,consoleLevel:i.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,cacheKeyPrefix:"logs-",postUrl:"/api/metrics",delayPostInMs:1000*60*10,getPingData:undefined,onServerResponse:undefined};i.prototype._init=function j(E){var D=this;D.options={};for(var C in i.defaultOptions){if(i.defaultOptions.hasOwnProperty(C)){D.options[C]=(E.hasOwnProperty(C))?(E[C]):(i.defaultOptions[C])}}D.options.logLevel=D._parseLevel(D.options.logLevel);D.options.consoleLevel=D._parseLevel(D.options.consoleLevel);D._sending=false;D._waiting=null;D._postSize=D.options.postSize;D._initCache();return D};i.prototype._initCache=function a(){try{this.cache=new z({maxSize:this.options.maxCacheSize,key:this.options.cacheKeyPrefix+this.userId})}catch(C){this._emitToConsole("warn","MetricsLogger",["Could not intitialize logging cache:",C]);this.options.logLevel=i.NONE}};i.prototype._parseLevel=function n(E){var D=typeof E;if(D==="number"){return E}if(D==="string"){var C=E.toUpperCase();if(i.hasOwnProperty(C)){return i[C]}}throw new Error("Unknown log level: "+E)};i.prototype.emit=function q(F,E,D){var C=this;E=E||C.options.defaultNamespace;if(!F||!D){return C}F=C._parseLevel(F);if(F>=C.options.logLevel){C._addToCache(F,E,D)}if(C.consoleLogger&&F>=C.options.consoleLevel){C._emitToConsole(F,E,D)}return C};i.prototype._addToCache=function b(H,E,D){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var C=this;try{var G=C.cache.add(C._buildEntry(H,E,D));if(G>=C._postSize){C._postCache()}}catch(F){C._emitToConsole("warn","MetricsLogger",["Metrics logger could not stringify logArguments:",E,D]);C._emitToConsole("error","MetricsLogger",[F])}return C};i.prototype._buildEntry=function u(F,D,C){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var E={level:F,namespace:this.options.clientPrefix+D,args:C};if(this.options.addTime){E.time=new Date().toISOString()}return E};i.prototype._postCache=function v(F){F=F||{};this._emitToConsole("info","MetricsLogger",["_postCache",F,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var E=this,H=F.count||E._postSize,C=E.cache.get(H),G=C.length,D=(typeof E.options.getPingData==="function")?(E.options.getPingData()):({});D.metrics=JSON.stringify(C);E._sending=true;return jQuery.post(E.options.postUrl,D).always(function(){E._sending=false}).fail(function(K,I,J){E._postSize=E.options.maxCacheSize;this.emit("error","MetricsLogger",["_postCache error:",K.readyState,K.status,K.responseJSON||K.responseText])}).done(function(I){if(typeof E.options.onServerResponse==="function"){E.options.onServerResponse(I)}E.cache.remove(G);E._postSize=E.options.postSize})};i.prototype._delayPost=function k(){var C=this;C._waiting=setTimeout(function(){C._waiting=null},C.options.delayPostInMs)};i.prototype._emitToConsole=function c(G,F,E){var C=this;if(!C.consoleLogger){return C}var D=Array.prototype.slice.call(E,0);D.unshift(F);if(G>=i.METRIC&&typeof(C.consoleLogger.info)==="function"){return C.consoleLogger.info.apply(C.consoleLogger,D)}else{if(G>=i.ERROR&&typeof(C.consoleLogger.error)==="function"){return C.consoleLogger.error.apply(C.consoleLogger,D)}else{if(G>=i.WARN&&typeof(C.consoleLogger.warn)==="function"){C.consoleLogger.warn.apply(C.consoleLogger,D)}else{if(G>=i.INFO&&typeof(C.consoleLogger.info)==="function"){C.consoleLogger.info.apply(C.consoleLogger,D)}else{if(G>=i.DEBUG&&typeof(C.consoleLogger.debug)==="function"){C.consoleLogger.debug.apply(C.consoleLogger,D)}else{if(typeof(C.consoleLogger.log)==="function"){C.consoleLogger.log.apply(C.consoleLogger,D)}}}}}}return C};i.prototype.log=function h(){this.emit(1,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};i.prototype.debug=function p(){this.emit(i.DEBUG,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};i.prototype.info=function x(){this.emit(i.INFO,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};i.prototype.warn=function w(){this.emit(i.WARN,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};i.prototype.error=function t(){this.emit(i.ERROR,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};i.prototype.metric=function r(){this.emit(i.METRIC,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};function z(D){var C=this;return C._init(D||{})}z.defaultOptions={maxSize:5000};z.prototype._init=function j(C){if(!this._hasStorage()){throw new Error("LoggingCache needs localStorage")}if(!C.key){throw new Error("LoggingCache needs key for localStorage")}this.key=C.key;this._initStorage();this.maxSize=C.maxSize||z.defaultOptions.maxSize;return this};z.prototype._hasStorage=function A(){var D="test";try{localStorage.setItem(D,D);localStorage.removeItem(D);return true}catch(C){return false}};z.prototype._initStorage=function m(){if(localStorage.getItem(this.key)===null){return this.empty()}return this};z.prototype.add=function o(E){var D=this,F=D._fetchAndParse(),C=(F.length+1)-D.maxSize;if(C>0){F.splice(0,C)}F.push(E);D._unparseAndStore(F);return F.length};z.prototype._fetchAndParse=function g(){var C=this;return JSON.parse(localStorage.getItem(C.key))};z.prototype._unparseAndStore=function f(C){var D=this;return localStorage.setItem(D.key,JSON.stringify(C))};z.prototype.length=function e(){return this._fetchAndParse().length};z.prototype.get=function y(C){return this._fetchAndParse().slice(0,C)};z.prototype.remove=function B(C){var E=this._fetchAndParse(),D=E.splice(0,C);this._unparseAndStore(E);return D};z.prototype.empty=function l(){localStorage.setItem(this.key,"[]");return this};z.prototype.stringify=function s(C){return JSON.stringify(this.get(C))};z.prototype.print=function d(){console.log(JSON.stringify(this._fetchAndParse(),null," "))};return{MetricsLogger:i,LoggingCache:z}});
\ No newline at end of file
diff -r f1c9df0b5cabb998dd82dc6a154f66677173ffb8 -r 6f8070735e6f36fd1cd7b79d7cef1d69ebf8c1d6 static/scripts/utils/metrics-logger.js
--- a/static/scripts/utils/metrics-logger.js
+++ b/static/scripts/utils/metrics-logger.js
@@ -3,8 +3,10 @@
/*global window, jQuery, console */
/*=============================================================================
TODO:
- broken pipe due to onunload post in webkit, safari
- need to use persistence
+ while anon: logs saved to 'logs-null' - this will never post
+ unless we manually do so at/after login
+ OR prepend when userId and localStorage has 'logs-null'
+ wire up _delayPost and test
=============================================================================*/
/** @class MetricsLogger
@@ -31,8 +33,7 @@
options = options || {};
var self = this;
- //TODO: this might be used if we store the logs in browser storage
- ///** */
+ ///** get the current user's id from bootstrapped data or options */
self.userId = window.bootstrapped? window.bootstrapped.user.id: null;
self.userId = self.userId || options.userId || null;
@@ -73,9 +74,13 @@
postSize : 1000,
/** T/F whether to add a timestamp to incoming cached messages */
addTime : true,
+ /** string to prefix to userid for cache web storage */
+ cacheKeyPrefix : 'logs-',
/** the relative url to post messages to */
postUrl : '/api/metrics',
+ /** delay before trying post again after two failures */
+ delayPostInMs : 1000 * 60 * 10,
/** an (optional) function that should return an object; used to send additional data with the metrics */
getPingData : undefined,
@@ -97,8 +102,13 @@
self.options.consoleLevel = self._parseLevel( self.options.consoleLevel );
//self._emitToConsole( 'debug', 'MetricsLogger', 'MetricsLogger.options:', self.options );
+ /** is the logger currently sending? */
self._sending = false;
+ /** the setTimeout id if the logger POST has failed more than once */
+ self._waiting = null;
+ /** the current number of entries to send in a POST */
self._postSize = self.options.postSize;
+
self._initCache();
return self;
@@ -106,8 +116,15 @@
/** initialize the cache */
MetricsLogger.prototype._initCache = function _initCache(){
- this.cache = new LoggingCache({ maxSize : this.options.maxCacheSize });
-
+ try {
+ this.cache = new LoggingCache({
+ maxSize : this.options.maxCacheSize,
+ key : this.options.cacheKeyPrefix + this.userId
+ });
+ } catch( err ){
+ this._emitToConsole( 'warn', 'MetricsLogger', [ 'Could not intitialize logging cache:', err ] );
+ this.options.logLevel = MetricsLogger.NONE;
+ }
};
/** return the numeric log level if level in 'none, debug, log, info, warn, error' */
@@ -134,7 +151,7 @@
return self;
}
// add to cache if proper level
-//TODO: respect do not track?
+ //TODO: respect do not track?
//if( !navigator.doNotTrack && level >= self.options.logLevel ){
level = self._parseLevel( level );
if( level >= self.options.logLevel ){
@@ -192,7 +209,6 @@
MetricsLogger.prototype._postCache = function _postCache( options ){
options = options || {};
this._emitToConsole( 'info', 'MetricsLogger', [ '_postCache', options, this._postSize ]);
-//TODO: remove jq dependence
// short circuit if we're already sending
if( !this.options.postUrl || this._sending ){
@@ -209,15 +225,22 @@
//console.debug( postSize, entriesLength );
// add the metrics and send
- postData.metrics = self._preprocessCache( entries );
+ postData.metrics = JSON.stringify( entries );
+ //console.debug( postData.metrics );
self._sending = true;
return jQuery.post( self.options.postUrl, postData )
.always( function(){
self._sending = false;
})
- .fail( function(){
+ .fail( function( xhr, status, message ){
// if we failed the previous time, set the next post target to the max num of entries
self._postSize = self.options.maxCacheSize;
+//TODO:??
+ // log this failure to explain any gap in metrics
+ this.emit( 'error', 'MetricsLogger', [ '_postCache error:',
+ xhr.readyState, xhr.status, xhr.responseJSON || xhr.responseText ]);
+//TODO: still doesn't solve the problem that when cache == max, post will be tried on every emit
+//TODO: see _delayPost
})
.done( function( response ){
if( typeof self.options.onServerResponse === 'function' ){
@@ -232,10 +255,13 @@
// return the xhr promise
};
-/** Preprocess a number of cache entries for sending to the server (stringification) */
-MetricsLogger.prototype._preprocessCache = function _preprocessCache( entries ){
- return [ '[', ( entries.join( ',\n' ) ), ']' ].join( '\n' );
- //return [ '[', ( entries.join( ',' ) ), ']' ].join( '' );
+/** set _waiting to true and, after delayPostInMs, set it back to false */
+MetricsLogger.prototype._delayPost = function _delayPost(){
+//TODO: this won't work between pages
+ var self = this;
+ self._waiting = setTimeout( function(){
+ self._waiting = null;
+ }, self.options.delayPostInMs );
};
@@ -306,7 +332,11 @@
};
-//=============================================================================
+/* ============================================================================
+TODO:
+ need a performance pass - the JSON un/parsing is a bit much
+
+============================================================================ */
/** @class LoggingCache
* Simple implementation of cache wrapping an array.
*
@@ -315,7 +345,6 @@
*/
function LoggingCache( options ){
var self = this;
- self._cache = [];
return self._init( options || {} );
}
@@ -327,52 +356,104 @@
/** initialize with options */
LoggingCache.prototype._init = function _init( options ){
+ if( !this._hasStorage() ){
+ //TODO: fall back to jstorage
+ throw new Error( 'LoggingCache needs localStorage' );
+ }
+ if( !options.key ){
+ throw new Error( 'LoggingCache needs key for localStorage' );
+ }
+ this.key = options.key;
+ this._initStorage();
+
this.maxSize = options.maxSize || LoggingCache.defaultOptions.maxSize;
return this;
};
+/** tests for localStorage fns */
+LoggingCache.prototype._hasStorage = function _hasStorage(){
+//TODO: modernizr
+ var test = 'test';
+ try {
+ localStorage.setItem( test, test );
+ localStorage.removeItem( test );
+ return true;
+ } catch( e ){
+ return false;
+ }
+};
+
+/** if no localStorage set for key, initialize to empty array */
+LoggingCache.prototype._initStorage = function _initStorage(){
+ if( localStorage.getItem( this.key ) === null ){
+ return this.empty();
+ }
+ return this;
+};
+
/** add an entry to the cache, removing the oldest beforehand if size >= maxSize */
LoggingCache.prototype.add = function add( entry ){
var self = this,
- overage = ( self.length() + 1 ) - self.maxSize;
+ _cache = self._fetchAndParse(),
+ overage = ( _cache.length + 1 ) - self.maxSize;
if( overage > 0 ){
- self.remove( overage );
+ _cache.splice( 0, overage );
}
- self._cache.push( self._preprocessEntry( entry ) );
- return self.length();
+ _cache.push( entry );
+ self._unparseAndStore( _cache );
+ return _cache.length;
};
-/** process the entry before caching */
-LoggingCache.prototype._preprocessEntry = function _preprocessEntry( entry ){
- return JSON.stringify( entry );
+/** get the entries from localStorage and parse them */
+LoggingCache.prototype._fetchAndParse = function _fetchAndParse(){
+ var self = this;
+ return JSON.parse( localStorage.getItem( self.key ) );
};
+/** stringify the entries and put them in localStorage */
+LoggingCache.prototype._unparseAndStore = function _unparseAndStore( entries ){
+ var self = this;
+ return localStorage.setItem( self.key, JSON.stringify( entries ) );
+};
+
+///** process the entry before caching */
+//LoggingCache.prototype._preprocessEntry = function _preprocessEntry( entry ){
+// return JSON.stringify( entry );
+//};
+
/** return the length --- oh, getters where are you? */
LoggingCache.prototype.length = function length(){
- return this._cache.length;
+ return this._fetchAndParse().length;
};
/** get count number of entries starting with the oldest */
LoggingCache.prototype.get = function get( count ){
- return this._cache.slice( 0, count );
+ return this._fetchAndParse().slice( 0, count );
};
/** remove count number of entries starting with the oldest */
LoggingCache.prototype.remove = function remove( count ){
- return this._cache.splice( 0, count );
+ var _cache = this._fetchAndParse(),
+ removed = _cache.splice( 0, count );
+ this._unparseAndStore( _cache );
+ return removed;
+};
+
+/** empty/clear the entire cache */
+LoggingCache.prototype.empty = function empty(){
+ localStorage.setItem( this.key, '[]' );
+ return this;
};
/** stringify count number of entries (but do not remove) */
LoggingCache.prototype.stringify = function stringify( count ){
- return [ '[', ( this.get( count ).join( ',\n' ) ), ']' ].join( '\n' );
+ return JSON.stringify( this.get( count ) );
};
/** outputs entire cache to console */
LoggingCache.prototype.print = function print(){
// popup? (really, carl? a popup?) - easier to copy/paste
- this._cache.forEach( function( entry ){
- console.log( entry );
- });
+ console.log( JSON.stringify( this._fetchAndParse(), null, ' ' ) );
};
diff -r f1c9df0b5cabb998dd82dc6a154f66677173ffb8 -r 6f8070735e6f36fd1cd7b79d7cef1d69ebf8c1d6 test/qunit/tests/metrics-logger.js
--- a/test/qunit/tests/metrics-logger.js
+++ b/test/qunit/tests/metrics-logger.js
@@ -22,9 +22,51 @@
self.lastMessage = { level: fnName, args: args };
};
});
+ return self;
+ };
+
+ var MockLocalStorage = function(){
+ var self = this;
+ self._storage = {};
+ self.setItem = function( k, v ){
+ self._storage[ k ] = v + '';
+ return undefined;
+ };
+ self.getItem = function( k ){
+ return self._storage.hasOwnProperty( k )? self._storage[ k ]: null;
+ };
+ self.removeItem = function( k ){
+ if( self._storage.hasOwnProperty( k ) ){
+ delete self._storage[ k ];
+ }
+ return undefined;
+ };
+ self.key = function( i ){
+ var index = 0;
+ for( var k in self._storage ){
+ if( self._storage.hasOwnProperty( k ) ){
+ if( i === index ){ return k; }
+ index += 1;
+ }
+ }
+ return null;
+ };
+ self.clear = function(){
+ self._storage = {};
+ };
+ // property - not worth it
+ //self.length = function(){};
+
+ return self;
+ };
+ window.localStorage = new MockLocalStorage();
+
+ ( window.bootstrapped = {} ).user = {
+ id : 'test'
};
module( "Metrics logger tests" );
+ console.debug( '\n' );
// ======================================================================== MetricsLogger
test( "logger construction/initializiation defaults", function() {
var logger = new metrics.MetricsLogger({});
@@ -68,11 +110,14 @@
var logger = new metrics.MetricsLogger({
logLevel : 'metric'
});
+ logger.cache.empty();
+
equal( logger.options.logLevel, metrics.MetricsLogger.METRIC );
logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] );
equal( logger.cache.length(), 1 );
- var cached = JSON.parse( logger.cache.get( 1 ) );
+ var cached = logger.cache.get( 1 )[0];
+ //console.debug( 'cached:', JSON.stringify( cached ) );
equal( cached.level, metrics.MetricsLogger.METRIC );
equal( cached.namespace, 'client.test' );
equal( cached.args.length, 3 );
@@ -85,6 +130,8 @@
var logger = new metrics.MetricsLogger({
logLevel : 'metric'
});
+ logger.cache.empty();
+
logger.emit( 'error', 'test', [ 1, 2, { three: 3 }] );
equal( logger.cache.length(), 0 );
});
@@ -93,6 +140,8 @@
var logger = new metrics.MetricsLogger({
logLevel : 'metric'
});
+ logger.cache.empty();
+
logger.emit( 'metric', 'test', [{ window: window }] );
equal( logger.cache.length(), 0 );
});
@@ -108,11 +157,14 @@
logLevel : 'metric',
onServerResponse : function( response ){ callback(); }
});
+ logger.cache.empty();
var server = sinon.fakeServer.create(),
metricsOnServer;
server.respondWith( 'POST', '/api/metrics', function( request ){
metricsOnServer = metricsFromRequestBody( request );
+ //console.debug( 'requestBody:', request.requestBody );
+ //console.debug( 'metricsOnServer:', JSON.stringify( metricsOnServer, null, ' ' ) );
request.respond(
200,
{ "Content-Type": "application/json" },
@@ -125,6 +177,7 @@
logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] );
logger._postCache();
server.respond();
+
ok( callback.calledOnce, 'onServerResponse was called' );
equal( logger.cache.length(), 0, 'should have emptied cache (on success)' );
equal( logger._postSize, 1000, '_postSize still at default' );
@@ -148,6 +201,7 @@
logLevel : 'metric',
onServerResponse : function( response ){ callback(); }
});
+ logger.cache.empty();
var server = sinon.fakeServer.create();
server.respondWith( 'POST', '/api/metrics', function( request ){
@@ -168,8 +222,6 @@
equal( logger.cache.length(), 1, 'should NOT have emptied cache' );
equal( logger._postSize, logger.options.maxCacheSize, '_postSize changed to max' );
- //TODO: still doesn't solve the problem that when cache == max, post will be tried on every emit
-
server.restore();
});
@@ -207,6 +259,8 @@
var logger = new metrics.MetricsLogger({
logLevel : 'all'
});
+ logger.cache.empty();
+
equal( logger.options.logLevel, metrics.MetricsLogger.ALL );
logger.log( 0 );
logger.debug( 1 );
@@ -216,7 +270,7 @@
logger.metric( 5 );
equal( logger.cache.length(), 6 );
- var cached = logger.cache.remove( 6 ).map( JSON.parse ),
+ var cached = logger.cache.remove( 6 ),
entry;
cached.forEach( function( entry ){
@@ -240,22 +294,39 @@
// ======================================================================== LoggingCache
test( "cache construction/initializiation defaults", function() {
- var cache = new metrics.LoggingCache();
+ // use empty to prevent tests stepping on one another due to persistence
+ var cache = new metrics.LoggingCache({ key: 'logs-test' }).empty();
equal( cache.maxSize, 5000 );
- equal( $.type( cache._cache ), 'array' );
+ equal( window.localStorage.getItem( 'logs-test' ), '[]' );
+ });
+
+ test( "cache construction/initializiation failure", function() {
+ ////TODO: doesn't work - readonly
+ //window.localStorage = null;
+ //console.debug( 'localStorage:', window.localStorage );
+ var oldFn = metrics.LoggingCache.prototype._hasStorage;
+ metrics.LoggingCache.prototype._hasStorage = function(){ return false; };
+ throws( function(){
+ return new metrics.LoggingCache({ key: 'logs-test' });
+ }, /LoggingCache needs localStorage/, 'lack of localStorage throws error' );
+ metrics.LoggingCache.prototype._hasStorage = oldFn;
+
+ throws( function(){
+ return new metrics.LoggingCache();
+ }, /LoggingCache needs key for localStorage/, 'lack of key throws error' );
});
test( "cache construction/initializiation setting max cache size", function() {
var cache = new metrics.LoggingCache({
+ key : 'logs-test',
maxSize : 5
- });
+ }).empty();
equal( cache.maxSize, 5 );
});
test( "cache plays well with no data", function() {
- var cache = new metrics.LoggingCache();
+ var cache = new metrics.LoggingCache({ key: 'logs-test' }).empty();
- equal( cache._cache.length, 0 );
equal( cache.length(), 0 );
var get = cache.get( 10 );
ok( jQuery.type( get ) === 'array' && get.length === 0 );
@@ -266,42 +337,59 @@
test( "cache add properly adds and removes data", function() {
var cache = new metrics.LoggingCache({
+ key : 'logs-test',
maxSize : 5
- });
+ }).empty();
+
var entry1 = [{ one: 1 }, 'two' ];
cache.add( entry1 );
- equal( cache._cache.length, 1 );
equal( cache.length(), 1 );
- equal( cache._cache[0], JSON.stringify( entry1 ) );
- equal( cache.get( 1 ), JSON.stringify( entry1 ) );
+ equal( JSON.stringify( cache.get( 1 )[0] ), JSON.stringify( entry1 ) );
var entry2 = { blah: { one: 1 }, bler: [ 'three', { two: 2 } ] };
cache.add( entry2 );
equal( cache.length(), 2 );
- equal( cache.stringify( 2 ), '[\n' + JSON.stringify( entry1 ) + ',\n' + JSON.stringify( entry2 ) + '\n]' );
+ equal( cache.stringify( 2 ), '[' + JSON.stringify( entry1 ) + ',' + JSON.stringify( entry2 ) + ']' );
// FIFO
var returned = cache.remove( 1 );
equal( cache.length(), 1 );
ok( jQuery.type( returned ) === 'array' && returned.length === 1 );
var returned0 = returned[0];
- ok( jQuery.type( returned0 ) === 'string' && returned0 === JSON.stringify( entry1 ) );
+ ok( jQuery.type( returned0 ) === 'array' && JSON.stringify( returned0 ) === JSON.stringify( entry1 ) );
});
test( "cache past max loses oldest", function() {
var cache = new metrics.LoggingCache({
+ key : 'logs-test',
maxSize : 5
- });
+ }).empty();
+
for( var i=0; i<10; i+=1 ){
cache.add({ index: i });
}
equal( cache.length(), 5 );
var get = cache.get( 5 );
- ok( JSON.parse( get[0] ).index === 5 );
- ok( JSON.parse( get[1] ).index === 6 );
- ok( JSON.parse( get[2] ).index === 7 );
- ok( JSON.parse( get[3] ).index === 8 );
- ok( JSON.parse( get[4] ).index === 9 );
+ ok( get[0].index === 5 );
+ ok( get[1].index === 6 );
+ ok( get[2].index === 7 );
+ ok( get[3].index === 8 );
+ ok( get[4].index === 9 );
});
+
+ test( "cache is properly persistent", function() {
+ var cache1 = new metrics.LoggingCache({ key : 'logs-test' }).empty(),
+ entry = [{ one: 1 }, 'two' ];
+ cache1.add( entry );
+ equal( cache1.length(), 1 );
+
+ var cache2 = new metrics.LoggingCache({ key : 'logs-test' });
+ equal( cache2.length(), 1, 'old key gets previously stored' );
+ equal( JSON.stringify( cache2.get( 1 )[0] ), JSON.stringify( entry ) );
+
+ var cache3 = new metrics.LoggingCache({ key : 'logs-bler' });
+ equal( cache3.length(), 0, 'new key causes new storage' );
+ });
+
});
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: Workflow running - modify var names/comment to reflect 773951eb2bbf.
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f1c9df0b5cab/
Changeset: f1c9df0b5cab
User: jmchilton
Date: 2014-04-21 15:36:43
Summary: Workflow running - modify var names/comment to reflect 773951eb2bbf.
Affected #: 1 file
diff -r 773951eb2bbf082842fdacc00901e4506d846acb -r f1c9df0b5cabb998dd82dc6a154f66677173ffb8 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -69,9 +69,9 @@
# Web controller will populate stateful modules on each step before calling invoke
# but not API controller. More work should be done to further harmonize these methods
# going forward if possible - if possible moving more web controller logic here.
- modules_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "state" )
- if not modules_populated:
- self._populate_modules( )
+ state_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "state" )
+ if not state_populated:
+ self._populate_state( )
for step in self.workflow.steps:
job = None
@@ -164,7 +164,7 @@
replacement = outputs[ connection[ 0 ].output_step.id ][ connection[ 0 ].output_name ]
return replacement
- def _populate_modules( self ):
+ def _populate_state( self ):
# Build the state for each step
for step in self.workflow.steps:
step_errors = None
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: jmchilton: Bugfix for 439510f (reported by @saketkc).
by commits-noreply@bitbucket.org 21 Apr '14
by commits-noreply@bitbucket.org 21 Apr '14
21 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/773951eb2bbf/
Changeset: 773951eb2bbf
User: jmchilton
Date: 2014-04-21 15:01:22
Summary: Bugfix for 439510f (reported by @saketkc).
Previous logic for determining if state had been calculated for workflow steps in workflow run module would only work for data input steps - this new logic should work for data input or tools.
Affected #: 1 file
diff -r 2360e50e3aad2fa3c98b7b43df9081653f82265d -r 773951eb2bbf082842fdacc00901e4506d846acb lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -69,7 +69,7 @@
# Web controller will populate stateful modules on each step before calling invoke
# but not API controller. More work should be done to further harmonize these methods
# going forward if possible - if possible moving more web controller logic here.
- modules_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "module" )
+ modules_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "state" )
if not modules_populated:
self._populate_modules( )
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
20 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2360e50e3aad/
Changeset: 2360e50e3aad
User: jmchilton
Date: 2014-04-20 18:25:40
Summary: Pack scripts.
Affected #: 1 file
diff -r 72774adb2ae8504d51200d0e3134ba9aa1e44aaa -r 2360e50e3aad2fa3c98b7b43df9081653f82265d static/scripts/packed/galaxy.workflow_editor.canvas.js
--- a/static/scripts/packed/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/packed/galaxy.workflow_editor.canvas.js
@@ -1,1 +1,1 @@
-function Terminal(a){this.element=a;this.connectors=[]}$.extend(Terminal.prototype,{connect:function(a){this.connectors.push(a);if(this.node){this.node.changed()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.changed()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});function OutputTerminal(a,b){Terminal.call(this,a);this.datatypes=b}OutputTerminal.prototype=new Terminal();function InputTerminal(b,c,a){Terminal.call(this,b);this.datatypes=c;this.multiple=a}InputTerminal.prototype=new Terminal();$.extend(InputTerminal.prototype,{can_accept:function(a){if(this.connectors.length<1||this.multiple){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});function Node(a){this.element=a;this.input_terminals={};this.output_terminals={};this.tool_errors={}}$.extend(Node.prototype,{new_input_terminal:function(a){var b=$("<div class='terminal input-terminal'></div>")[0];this.enable_input_terminal(b,a.name,a.extensions,a.multiple);return b},enable_input_terminal:function(f,b,d,a){var g=this;var c=f.terminal=new InputTerminal(f,d,a);c.node=g;c.name=b;$(f).bind("dropinit",function(h,i){return $(i.drag).hasClass("output-terminal")&&c.can_accept(i.drag.terminal)}).bind("dropstart",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#BBFFBB"}}).bind("dropend",function(h,i){if(i.proxy.terminal){i.proxy.terminal.connectors[0].inner_color="#FFFFFF"}}).bind("drop",function(h,i){(new Connector(i.drag.terminal,c)).redraw()}).bind("hover",function(){if(c.connectors.length>0){var h=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(c.connectors,function(j,i){if(i){i.destroy()}});h.remove()}))).bind("mouseleave",function(){$(this).remove()});h.css({top:$(f).offset().top-2,left:$(f).offset().left-h.width(),"padding-right":$(f).width()}).show()}});g.input_terminals[b]=c},enable_output_terminal:function(d,a,f){var g=this;var c=d;var b=d.terminal=new OutputTerminal(d,f);b.node=g;b.name=a;$(d).bind("dragstart",function(j,k){$(k.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var i=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);i.terminal=new OutputTerminal(i);var l=new Connector();l.dragging=true;l.connect(d.terminal,i.terminal);return i}).bind("drag",function(i,j){var h=function(){var l=$(j.proxy).offsetParent().offset(),k=j.offsetX-l.left,m=j.offsetY-l.top;$(j.proxy).css({left:k,top:m});j.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};h();$("#canvas-container").get(0).scroll_panel.test(i,h)}).bind("dragend",function(h,i){i.proxy.terminal.connectors[0].destroy();$(i.proxy).remove();$(i.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()});g.output_terminals[a]=b},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(h){var g=this.element;if(h.type){this.type=h.type}this.name=h.name;this.form_html=h.form_html;this.tool_state=h.tool_state;this.tool_errors=h.tool_errors;this.tooltip=h.tooltip?h.tooltip:"";this.annotation=h.annotation;this.post_job_actions=h.post_job_actions?h.post_job_actions:{};this.workflow_outputs=h.workflow_outputs?h.workflow_outputs:[];if(this.tool_errors){g.addClass("tool-node-error")}else{g.removeClass("tool-node-error")}var d=this;var c=Math.max(150,g.width());var a=g.find(".toolFormBody");a.find("div").remove();var i=$("<div class='inputs'></div>").appendTo(a);$.each(h.data_inputs,function(k,f){var j=d.new_input_terminal(f);var b=$("<div class='form-row dataRow input-data-row' name='"+f.name+"'>"+f.label+"</div>");b.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(b);c=Math.max(c,b.outerWidth());b.css({position:"",left:"",top:"",display:""});b.remove();i.append(b.prepend(j))});if((h.data_inputs.length>0)&&(h.data_outputs.length>0)){a.append($("<div class='rule'></div>"))}$.each(h.data_outputs,function(k,b){var j=$("<div class='terminal output-terminal'></div>");d.enable_output_terminal(j[0],b.name,b.extensions);var f=b.name;if(b.extensions.indexOf("input")<0){f=f+" ("+b.extensions.join(", ")+")"}var m=$("<div class='form-row dataRow'>"+f+"</div>");if(d.type=="tool"){var l=$("<div class='callout "+f+"'></div>").css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(b.name,d.workflow_outputs)!=-1){d.workflow_outputs.splice($.inArray(b.name,d.workflow_outputs),1);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{d.workflow_outputs.push(b.name);l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});l.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});l.show();m.append(l);if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}m.hover(function(){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")},function(){if($.inArray(b.name,d.workflow_outputs)===-1){l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{l.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}})}m.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(m);c=Math.max(c,m.outerWidth()+17);m.css({position:"",left:"",top:"",display:""});m.detach();a.append(m.append(j))});g.css("width",Math.min(250,Math.max(g.width(),c)));workflow.node_changed(this)},update_field_data:function(d){var b=$(this.element),c=this;this.tool_state=d.tool_state;this.form_html=d.form_html;this.tool_errors=d.tool_errors;this.annotation=d.annotation;var f=$.parseJSON(d.post_job_actions);this.post_job_actions=f?f:{};if(this.tool_errors){b.addClass("tool-node-error")}else{b.removeClass("tool-node-error")}var g=b.find("div.inputs");var a=$("<div class='inputs'></div>");$.each(d.data_inputs,function(k,h){var j=c.new_input_terminal(h);g.find("div[name='"+h.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var i=this.terminal.connectors[0];if(i){j.terminal.connectors[0]=i;i.handle2=j.terminal}});$(this).remove()});a.append($("<div class='form-row dataRow input-data-row' name='"+h.name+"'>"+h.label+"</div>").prepend(j))});g.replaceWith(a);g.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.changed();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},changed:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node(i);g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
+var Terminal=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.connectors=[]},connect:function(a){this.connectors.push(a);if(this.node){this.node.markChanged()}},disconnect:function(a){this.connectors.splice($.inArray(a,this.connectors),1);if(this.node){this.node.markChanged()}},redraw:function(){$.each(this.connectors,function(a,b){b.redraw()})},destroy:function(){$.each(this.connectors.slice(),function(a,b){b.destroy()})}});var OutputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes}});var InputTerminal=Terminal.extend({initialize:function(a){Terminal.prototype.initialize.call(this,a);this.datatypes=a.datatypes;this.multiple=a.multiple},can_accept:function(a){if(this.connectors.length<1||this.multiple){for(var c in this.datatypes){var f=new Array();f=f.concat(a.datatypes);if(a.node.post_job_actions){for(var d in a.node.post_job_actions){var g=a.node.post_job_actions[d];if(g.action_type=="ChangeDatatypeAction"&&(g.output_name==""||g.output_name==a.name)&&g.action_arguments){f.push(g.action_arguments.newtype)}}}for(var b in f){if(f[b]=="input"||issubtype(f[b],this.datatypes[c])){return true}}}}return false}});function Connector(b,a){this.canvas=null;this.dragging=false;this.inner_color="#FFFFFF";this.outer_color="#D8B365";if(b&&a){this.connect(b,a)}}$.extend(Connector.prototype,{connect:function(b,a){this.handle1=b;if(this.handle1){this.handle1.connect(this)}this.handle2=a;if(this.handle2){this.handle2.connect(this)}},destroy:function(){if(this.handle1){this.handle1.disconnect(this)}if(this.handle2){this.handle2.disconnect(this)}$(this.canvas).remove()},redraw:function(){var d=$("#canvas-container");if(!this.canvas){this.canvas=document.createElement("canvas");if(window.G_vmlCanvasManager){G_vmlCanvasManager.initElement(this.canvas)}d.append($(this.canvas));if(this.dragging){this.canvas.style.zIndex="300"}}var n=function(c){return $(c).offset().left-d.offset().left};var i=function(c){return $(c).offset().top-d.offset().top};if(!this.handle1||!this.handle2){return}var h=n(this.handle1.element)+5;var g=i(this.handle1.element)+5;var p=n(this.handle2.element)+5;var m=i(this.handle2.element)+5;var f=100;var k=Math.min(h,p);var a=Math.max(h,p);var j=Math.min(g,m);var t=Math.max(g,m);var b=Math.min(Math.max(Math.abs(t-j)/2,100),300);var o=k-f;var s=j-f;var q=a-k+2*f;var l=t-j+2*f;this.canvas.style.left=o+"px";this.canvas.style.top=s+"px";this.canvas.setAttribute("width",q);this.canvas.setAttribute("height",l);h-=o;g-=s;p-=o;m-=s;var r=this.canvas.getContext("2d");r.lineCap="round";r.strokeStyle=this.outer_color;r.lineWidth=7;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke();r.strokeStyle=this.inner_color;r.lineWidth=5;r.beginPath();r.moveTo(h,g);r.bezierCurveTo(h+b,g,p-b,m,p,m);r.stroke()}});var Node=Backbone.Model.extend({initialize:function(a){this.element=a.element;this.input_terminals={};this.output_terminals={};this.tool_errors={}},redraw:function(){$.each(this.input_terminals,function(a,b){b.redraw()});$.each(this.output_terminals,function(a,b){b.redraw()})},destroy:function(){$.each(this.input_terminals,function(a,b){b.destroy()});$.each(this.output_terminals,function(a,b){b.destroy()});workflow.remove_node(this);$(this.element).remove()},make_active:function(){$(this.element).addClass("toolForm-active")},make_inactive:function(){var a=this.element.get(0);(function(b){b.removeChild(a);b.appendChild(a)})(a.parentNode);$(a).removeClass("toolForm-active")},init_field_data:function(b){if(b.type){this.type=b.type}this.name=b.name;this.form_html=b.form_html;this.tool_state=b.tool_state;this.tool_errors=b.tool_errors;this.tooltip=b.tooltip?b.tooltip:"";this.annotation=b.annotation;this.post_job_actions=b.post_job_actions?b.post_job_actions:{};this.workflow_outputs=b.workflow_outputs?b.workflow_outputs:[];var a=this;var c=new NodeView({el:this.element[0],node:a,});a.nodeView=c;$.each(b.data_inputs,function(f,d){c.addDataInput(d)});if((b.data_inputs.length>0)&&(b.data_outputs.length>0)){c.addRule()}$.each(b.data_outputs,function(f,d){c.addDataOutput(d)});c.render();workflow.node_changed(this)},update_field_data:function(c){var b=this;nodeView=b.nodeView;this.tool_state=c.tool_state;this.form_html=c.form_html;this.tool_errors=c.tool_errors;this.annotation=c.annotation;var d=$.parseJSON(c.post_job_actions);this.post_job_actions=d?d:{};b.nodeView.renderToolErrors();var f=nodeView.$("div.inputs");var a=nodeView.newInputsDiv();$.each(c.data_inputs,function(h,g){b.nodeView.replaceDataInput(g,a)});f.replaceWith(a);f.find("div.input-data-row > .terminal").each(function(){this.terminal.destroy()});this.markChanged();this.redraw()},error:function(d){var a=$(this.element).find(".toolFormBody");a.find("div").remove();var c="<div style='color: red; text-style: italic;'>"+d+"</div>";this.form_html=c;a.html(c);workflow.node_changed(this)},markChanged:function(){workflow.node_changed(this)}});function Workflow(a){this.canvas_container=a;this.id_counter=0;this.nodes={};this.name=null;this.has_changes=false;this.active_form_has_changes=false}$.extend(Workflow.prototype,{add_node:function(a){a.id=this.id_counter;a.element.attr("id","wf-node-step-"+a.id);this.id_counter++;this.nodes[a.id]=a;this.has_changes=true;a.workflow=this},remove_node:function(a){if(this.active_node==a){this.clear_active_node()}delete this.nodes[a.id];this.has_changes=true},remove_all:function(){wf=this;$.each(this.nodes,function(b,a){a.destroy();wf.remove_node(a)})},rectify_workflow_outputs:function(){var b=false;var a=false;$.each(this.nodes,function(c,d){if(d.workflow_outputs&&d.workflow_outputs.length>0){b=true}$.each(d.post_job_actions,function(g,f){if(f.action_type==="HideDatasetAction"){a=true}})});if(b!==false||a!==false){$.each(this.nodes,function(c,g){if(g.type==="tool"){var f=false;if(g.post_job_actions==null){g.post_job_actions={};f=true}var d=[];$.each(g.post_job_actions,function(i,h){if(h.action_type=="HideDatasetAction"){d.push(i)}});if(d.length>0){$.each(d,function(h,j){f=true;delete g.post_job_actions[j]})}if(b){$.each(g.output_terminals,function(i,j){var h=true;$.each(g.workflow_outputs,function(l,m){if(j.name===m){h=false}});if(h===true){f=true;var k={action_type:"HideDatasetAction",output_name:j.name,action_arguments:{}};g.post_job_actions["HideDatasetAction"+j.name]=null;g.post_job_actions["HideDatasetAction"+j.name]=k}})}if(workflow.active_node==g&&f===true){workflow.reload_active_node()}}})}},to_simple:function(){var a={};$.each(this.nodes,function(c,f){var g={};$.each(f.input_terminals,function(i,j){g[j.name]=null;var h=[];$.each(j.connectors,function(k,l){h[k]={id:l.handle1.node.id,output_name:l.handle1.name};g[j.name]=h})});var b={};if(f.post_job_actions){$.each(f.post_job_actions,function(j,h){var k={action_type:h.action_type,output_name:h.output_name,action_arguments:h.action_arguments};b[h.action_type+h.output_name]=null;b[h.action_type+h.output_name]=k})}if(!f.workflow_outputs){f.workflow_outputs=[]}var d={id:f.id,type:f.type,tool_id:f.tool_id,tool_state:f.tool_state,tool_errors:f.tool_errors,input_connections:g,position:$(f.element).position(),annotation:f.annotation,post_job_actions:f.post_job_actions,workflow_outputs:f.workflow_outputs};a[f.id]=d});return{steps:a}},from_simple:function(b){wf=this;var c=0;wf.name=b.name;var a=false;$.each(b.steps,function(g,f){var d=prebuild_node(f.type,f.name,f.tool_id);d.init_field_data(f);if(f.position){d.element.css({top:f.position.top,left:f.position.left})}d.id=f.id;wf.nodes[d.id]=d;c=Math.max(c,parseInt(g));if(!a&&d.type==="tool"){if(d.workflow_outputs.length>0){a=true}else{$.each(d.post_job_actions,function(i,h){if(h.action_type==="HideDatasetAction"){a=true}})}}});wf.id_counter=c+1;$.each(b.steps,function(g,f){var d=wf.nodes[g];$.each(f.input_connections,function(i,h){if(h){if(!$.isArray(h)){h=[h]}$.each(h,function(k,j){var m=wf.nodes[j.id];var n=new Connector();n.connect(m.output_terminals[j.output_name],d.input_terminals[i]);n.redraw()})}});if(a&&d.type==="tool"){$.each(d.output_terminals,function(h,i){if(d.post_job_actions["HideDatasetAction"+i.name]===undefined){d.workflow_outputs.push(i.name);callout=$(d.element).find(".callout."+i.name);callout.find("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png");workflow.has_changes=true}})}})},check_changes_in_active_form:function(){if(this.active_form_has_changes){this.has_changes=true;$("#right-content").find("form").submit();this.active_form_has_changes=false}},reload_active_node:function(){if(this.active_node){var a=this.active_node;this.clear_active_node();this.activate_node(a)}},clear_active_node:function(){if(this.active_node){this.active_node.make_inactive();this.active_node=null}parent.show_form_for_tool("<div>No node selected</div>")},activate_node:function(a){if(this.active_node!=a){this.check_changes_in_active_form();this.clear_active_node();parent.show_form_for_tool(a.form_html+a.tooltip,a);a.make_active();this.active_node=a}},node_changed:function(a){this.has_changes=true;if(this.active_node==a){this.check_changes_in_active_form();parent.show_form_for_tool(a.form_html+a.tooltip,a)}},layout:function(){this.check_changes_in_active_form();this.has_changes=true;var i={};var b={};$.each(this.nodes,function(l,k){if(i[l]===undefined){i[l]=0}if(b[l]===undefined){b[l]=[]}});$.each(this.nodes,function(l,k){$.each(k.input_terminals,function(m,n){$.each(n.connectors,function(p,q){var o=q.handle1.node;i[k.id]+=1;b[o.id].push(k.id)})})});node_ids_by_level=[];while(true){level_parents=[];for(var a in i){if(i[a]==0){level_parents.push(a)}}if(level_parents.length==0){break}node_ids_by_level.push(level_parents);for(var f in level_parents){var j=level_parents[f];delete i[j];for(var g in b[j]){i[b[j][g]]-=1}}}if(i.length){return}var d=this.nodes;var h=80;v_pad=30;var c=h;$.each(node_ids_by_level,function(k,l){l.sort(function(p,o){return $(d[p].element).position().top-$(d[o].element).position().top});var m=0;var n=v_pad;$.each(l,function(o,r){var q=d[r];var p=$(q.element);$(p).css({top:n,left:c});m=Math.max(m,$(p).width());n+=$(p).height()+v_pad});c+=m+h});$.each(d,function(k,l){l.redraw()})},bounds_for_all_nodes:function(){var d=Infinity,b=-Infinity,c=Infinity,a=-Infinity,f;$.each(this.nodes,function(h,g){e=$(g.element);f=e.position();d=Math.min(d,f.left);b=Math.max(b,f.left+e.width());c=Math.min(c,f.top);a=Math.max(a,f.top+e.width())});return{xmin:d,xmax:b,ymin:c,ymax:a}},fit_canvas_to_nodes:function(){var a=this.bounds_for_all_nodes();var f=this.canvas_container.position();var i=this.canvas_container.parent();var d=fix_delta(a.xmin,100);var h=fix_delta(a.ymin,100);d=Math.max(d,f.left);h=Math.max(h,f.top);var c=f.left-d;var g=f.top-h;var b=round_up(a.xmax+100,100)+d;var j=round_up(a.ymax+100,100)+h;b=Math.max(b,-c+i.width());j=Math.max(j,-g+i.height());this.canvas_container.css({left:c,top:g,width:b,height:j});this.canvas_container.children().each(function(){var k=$(this).position();$(this).css("left",k.left+d);$(this).css("top",k.top+h)})}});function fix_delta(a,b){if(a<b||a>3*b){new_pos=(Math.ceil(((a%b))/b)+1)*b;return(-(a-new_pos))}return 0}function round_up(a,b){return Math.ceil(a/b)*b}function prebuild_node(l,j,r){var i=$("<div class='toolForm toolFormInCanvas'></div>");var g=new Node({element:i});g.type=l;if(l=="tool"){g.tool_id=r}var n=$("<div class='toolFormTitle unselectable'>"+j+"</div>");i.append(n);i.css("left",$(window).scrollLeft()+20);i.css("top",$(window).scrollTop()+20);var m=$("<div class='toolFormBody'></div>");var h="<div><img height='16' align='middle' src='"+galaxy_config.root+"static/images/loading_small_white_bg.gif'/> loading tool info...</div>";m.append(h);g.form_html=h;i.append(m);var k=$("<div class='buttons' style='float: right;'></div>");k.append($("<div>").addClass("fa-icon-button fa fa-times").click(function(b){g.destroy()}));i.appendTo("#canvas-container");var d=$("#canvas-container").position();var c=$("#canvas-container").parent();var a=i.width();var q=i.height();i.css({left:(-d.left)+(c.width()/2)-(a/2),top:(-d.top)+(c.height()/2)-(q/2)});k.prependTo(n);a+=(k.width()+10);i.css("width",a);$(i).bind("dragstart",function(){workflow.activate_node(g)}).bind("dragend",function(){workflow.node_changed(this);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview()}).bind("dragclickonly",function(){workflow.activate_node(g)}).bind("drag",function(o,p){var f=$(this).offsetParent().offset(),b=p.offsetX-f.left,s=p.offsetY-f.top;$(this).css({left:b,top:s});$(this).find(".terminal").each(function(){this.terminal.redraw()})});return g}function add_node(b,d,a){var c=prebuild_node(b,d,a);workflow.add_node(c);workflow.fit_canvas_to_nodes();canvas_manager.draw_overview();workflow.activate_node(c);return c}var ext_to_type=null;var type_to_type=null;function issubtype(b,a){b=ext_to_type[b];a=ext_to_type[a];return(type_to_type[b])&&(a in type_to_type[b])}function populate_datatype_info(a){ext_to_type=a.ext_to_class_name;type_to_type=a.class_to_classes}var NodeView=Backbone.View.extend({initialize:function(a){this.node=a.node;this.output_width=Math.max(150,this.$el.width());this.tool_body=this.$el.find(".toolFormBody");this.tool_body.find("div").remove();this.newInputsDiv().appendTo(this.tool_body)},render:function(){this.renderToolErrors();this.$el.css("width",Math.min(250,Math.max(this.$el.width(),this.output_width)))},renderToolErrors:function(){if(this.node.tool_errors){this.$el.addClass("tool-node-error")}else{this.$el.removeClass("tool-node-error")}},newInputsDiv:function(){return $("<div class='inputs'></div>")},updateMaxWidth:function(a){this.output_width=Math.max(this.output_width,a)},addRule:function(){this.tool_body.append($("<div class='rule'></div>"))},addDataInput:function(c){var d=new InputTerminalView({node:this.node,input:c});var f=d.el;var b=new DataInputView({terminalElement:f,input:c,nodeView:this,});var a=b.$el;var f=b.terminalElement;this.$(".inputs").append(a.prepend(f))},replaceDataInput:function(c,f){var g=new InputTerminalView({node:this.node,input:c});var d=g.el;this.$("div[name='"+c.name+"']").each(function(){$(this).find(".input-terminal").each(function(){var h=this.terminal.connectors[0];if(h){d.terminal.connectors[0]=h;h.handle2=d.terminal}});$(this).remove()});var b=new DataInputView({terminalElement:d,input:c,nodeView:this,skipResize:true,});var a=b.$el;f.append(a.prepend(d))},addDataOutput:function(a){var c=new OutputTerminalView({node:this.node,output:a});var b=new DataOutputView({output:a,terminalElement:c.el,nodeView:this,});this.tool_body.append(b.$el.append(b.terminalElement))}});var DataInputView=Backbone.View.extend({className:"form-row dataRow input-data-row",initialize:function(a){this.input=a.input;this.nodeView=a.nodeView;this.terminalElement=a.terminalElement;this.$el.attr("name",this.input.name).html(this.input.label);if(!a.skipResize){this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth());this.$el.css({position:"",left:"",top:"",display:""});this.$el.remove()}},});var OutputCalloutView=Backbone.View.extend({tagName:"div",initialize:function(b){this.label=b.label;this.node=b.node;this.output=b.output;var a=this;this.$el.attr("class","callout "+this.label).css({display:"none"}).append($("<div class='buttons'></div>").append($("<img/>").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png").click(function(){if($.inArray(a.output.name,a.node.workflow_outputs)!=-1){a.node.workflow_outputs.splice($.inArray(a.output.name,a.node.workflow_outputs),1);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{a.node.workflow_outputs.push(a.output.name);a.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}workflow.has_changes=true;canvas_manager.draw_overview()}))).tooltip({delay:500,title:"Mark dataset as a workflow output. All unmarked datasets will be hidden."});this.$el.css({top:"50%",margin:"-8px 0px 0px 0px",right:8});this.$el.show();this.resetImage()},resetImage:function(){if($.inArray(this.output.name,this.node.workflow_outputs)===-1){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-outline.png")}else{this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small.png")}},hoverImage:function(){this.$("img").attr("src",galaxy_config.root+"static/images/fugue/asterisk-small-yellow.png")}});var DataOutputView=Backbone.View.extend({className:"form-row dataRow",initialize:function(c){this.output=c.output;this.terminalElement=c.terminalElement;this.nodeView=c.nodeView;var a=this.output;var b=a.name;var d=this.nodeView.node;if(a.extensions.indexOf("input")<0){b=b+" ("+a.extensions.join(", ")+")"}this.$el.html(b);if(d.type=="tool"){var f=new OutputCalloutView({label:b,output:a,node:d,});this.$el.append(f.el);this.$el.hover(function(){f.hoverImage()},function(){f.resetImage()})}this.$el.css({position:"absolute",left:-1000,top:-1000,display:"none"});$("body").append(this.el);this.nodeView.updateMaxWidth(this.$el.outerWidth()+17);this.$el.css({position:"",left:"",top:"",display:""}).detach()}});var InputTerminalView=Backbone.View.extend({className:"terminal input-terminal",initialize:function(d){var h=d.node;var b=d.input;var c=b.name;var g=b.extensions;var a=b.multiple;var f=this.el.terminal=new InputTerminal({element:this.el,datatypes:g,multiple:a});f.node=h;f.name=c;h.input_terminals[c]=f},events:{dropinit:"onDropInit",dropstart:"onDropStart",dropend:"onDropEnd",drop:"onDrop",hover:"onHover",},onDropInit:function(b,c){var a=this.el.terminal;return $(c.drag).hasClass("output-terminal")&&a.can_accept(c.drag.terminal)},onDropStart:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#BBFFBB"}},onDropEnd:function(a,b){if(b.proxy.terminal){b.proxy.terminal.connectors[0].inner_color="#FFFFFF"}},onDrop:function(b,c){var a=this.el.terminal;new Connector(c.drag.terminal,a).redraw()},onHover:function(){var c=this.el;var b=c.terminal;if(b.connectors.length>0){var a=$("<div class='callout'></div>").css({display:"none"}).appendTo("body").append($("<div class='button'></div>").append($("<div/>").addClass("fa-icon-button fa fa-times").click(function(){$.each(b.connectors,function(f,d){if(d){d.destroy()}});a.remove()}))).bind("mouseleave",function(){$(this).remove()});a.css({top:$(c).offset().top-2,left:$(c).offset().left-a.width(),"padding-right":$(c).width()}).show()}},});var OutputTerminalView=Backbone.View.extend({className:"terminal output-terminal",initialize:function(c){var i=c.node;var a=c.output;var b=a.name;var h=a.extensions;var g=this.el;var f=g;var d=g.terminal=new OutputTerminal({element:g,datatypes:h});d.node=i;d.name=b;i.output_terminals[b]=d},events:{drag:"onDrag",dragstart:"onDragStart",dragend:"onDragEnd",},onDrag:function(b,c){var a=function(){var f=$(c.proxy).offsetParent().offset(),d=c.offsetX-f.left,g=c.offsetY-f.top;$(c.proxy).css({left:d,top:g});c.proxy.terminal.redraw();canvas_manager.update_viewport_overlay()};a();$("#canvas-container").get(0).scroll_panel.test(b,a)},onDragStart:function(b,f){$(f.available).addClass("input-terminal-active");workflow.check_changes_in_active_form();var a=$('<div class="drag-terminal" style="position: absolute;"></div>').appendTo("#canvas-container").get(0);a.terminal=new OutputTerminal({element:a});var g=new Connector();g.dragging=true;g.connect(this.el.terminal,a.terminal);return a},onDragEnd:function(a,b){b.proxy.terminal.connectors[0].destroy();$(b.proxy).remove();$(b.available).removeClass("input-terminal-active");$("#canvas-container").get(0).scroll_panel.stop()}});function ScrollPanel(a){this.panel=a}$.extend(ScrollPanel.prototype,{test:function(v,d){clearTimeout(this.timeout);var k=v.pageX,j=v.pageY,l=$(this.panel),c=l.position(),b=l.width(),i=l.height(),w=l.parent(),s=w.width(),a=w.height(),r=w.offset(),p=r.left,m=r.top,A=p+w.width(),u=m+w.height(),B=-(b-(s/2)),z=-(i-(a/2)),g=(s/2),f=(a/2),h=false,q=5,o=23;if(k-q<p){if(c.left<g){var n=Math.min(o,g-c.left);l.css("left",c.left+n);h=true}}else{if(k+q>A){if(c.left>B){var n=Math.min(o,c.left-B);l.css("left",c.left-n);h=true}}else{if(j-q<m){if(c.top<f){var n=Math.min(o,f-c.top);l.css("top",c.top+n);h=true}}else{if(j+q>u){if(c.top>z){var n=Math.min(o,c.top-B);l.css("top",(c.top-n)+"px");h=true}}}}}if(h){d();var l=this;this.timeout=setTimeout(function(){l.test(v,d)},50)}},stop:function(b,a){clearTimeout(this.timeout)}});function CanvasManager(b,a){this.cv=b;this.cc=this.cv.find("#canvas-container");this.oc=a.find("#overview-canvas");this.ov=a.find("#overview-viewport");this.init_drag()}$.extend(CanvasManager.prototype,{init_drag:function(){var b=this;var a=function(f,g){f=Math.min(f,b.cv.width()/2);f=Math.max(f,-b.cc.width()+b.cv.width()/2);g=Math.min(g,b.cv.height()/2);g=Math.max(g,-b.cc.height()+b.cv.height()/2);b.cc.css({left:f,top:g});b.update_viewport_overlay()};this.cc.each(function(){this.scroll_panel=new ScrollPanel(this)});var d,c;this.cv.bind("dragstart",function(){var g=$(this).offset();var f=b.cc.position();c=f.top-g.top;d=f.left-g.left}).bind("drag",function(f,g){a(g.offsetX+d,g.offsetY+c)}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});this.ov.bind("drag",function(k,l){var h=b.cc.width(),n=b.cc.height(),m=b.oc.width(),j=b.oc.height(),f=$(this).offsetParent().offset(),i=l.offsetX-f.left,g=l.offsetY-f.top;a(-(i/m*h),-(g/j*n))}).bind("dragend",function(){workflow.fit_canvas_to_nodes();b.draw_overview()});$("#overview-border").bind("drag",function(g,i){var j=$(this).offsetParent();var h=j.offset();var f=Math.max(j.width()-(i.offsetX-h.left),j.height()-(i.offsetY-h.top));$(this).css({width:f,height:f});b.draw_overview()});$("#overview-border div").bind("drag",function(){})},update_viewport_overlay:function(){var b=this.cc,f=this.cv,a=this.oc,c=this.ov,d=b.width(),j=b.height(),i=a.width(),g=a.height(),h=b.position();c.css({left:-(h.left/d*i),top:-(h.top/j*g),width:(f.width()/d*i)-2,height:(f.height()/j*g)-2})},draw_overview:function(){var j=$("#overview-canvas"),m=j.parent().parent().width(),i=j.get(0).getContext("2d"),d=$("#canvas-container").width(),l=$("#canvas-container").height();var g,a,k,f;var h=this.cv.width();var b=this.cv.height();if(d<h&&l<b){k=d/h*m;f=(m-k)/2;g=l/b*m;a=(m-g)/2}else{if(d<l){a=0;g=m;k=Math.ceil(g*d/l);f=(m-k)/2}else{k=m;f=0;g=Math.ceil(k*l/d);a=(m-g)/2}}j.parent().css({left:f,top:a,width:k,height:g});j.attr("width",k);j.attr("height",g);$.each(workflow.nodes,function(t,q){i.fillStyle="#D2C099";i.strokeStyle="#D8B365";i.lineWidth=1;var s=$(q.element),n=s.position(),c=n.left/d*k,r=n.top/l*g,o=s.width()/d*k,p=s.height()/l*g;if(q.tool_errors){i.fillStyle="#FFCCCC";i.strokeStyle="#AA6666"}else{if(q.workflow_outputs!=undefined&&q.workflow_outputs.length>0){i.fillStyle="#E8A92D";i.strokeStyle="#E8A92D"}}i.fillRect(c,r,o,p);i.strokeRect(c,r,o,p)});this.update_viewport_overlay()}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: davebgx: Fix issue where install and test framework would hang if a repository was not found in the database.
by commits-noreply@bitbucket.org 20 Apr '14
by commits-noreply@bitbucket.org 20 Apr '14
20 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/72774adb2ae8/
Changeset: 72774adb2ae8
User: davebgx
Date: 2014-04-20 05:24:12
Summary: Fix issue where install and test framework would hang if a repository was not found in the database.
Affected #: 1 file
diff -r 991f6ba12df4dddcded9a813bd5e55e70ad31841 -r 72774adb2ae8504d51200d0e3134ba9aa1e44aaa test/install_and_test_tool_shed_repositories/base/util.py
--- a/test/install_and_test_tool_shed_repositories/base/util.py
+++ b/test/install_and_test_tool_shed_repositories/base/util.py
@@ -598,8 +598,8 @@
# Get the repository record now that the tests that install it have completed.
repository = get_repository( name, owner, changeset_revision )
if repository is None:
- error_message = 'Error getting revision %s of repository %s owned by %s: %s' % ( changeset_revision, name, owner, str( e ) )
- log.exception( error_message )
+ error_message = 'Error getting revision %s of repository %s owned by %s: An entry for the repository was not found in the database.' % ( changeset_revision, name, owner )
+ log.error( error_message )
return repository, error_message
def is_excluded( exclude_list_dicts, name, owner, changeset_revision, encoded_repository_metadata_id ):
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
15 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/24539736d933/
Changeset: 24539736d933
User: jmchilton
Date: 2014-04-10 22:46:06
Summary: Workflow editor backbonification - add NodeView.
Including unit tests.
Affected #: 2 files
diff -r 12e6db99d15193b700cbde74f31c71a2ef9bcc2d -r 24539736d9331e3586a2e9cc32ee31da43105900 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -68,6 +68,58 @@
}
});
+
+//////////////
+// START VIEWS
+//////////////
+
+
+
+var NodeView = Backbone.View.extend( {
+ initialize: function( options ){
+ this.node = options.node;
+ this.output_width = Math.max(150, this.$el.width());
+ this.tool_body = this.$el.find( ".toolFormBody" );
+ this.tool_body.find( "div" ).remove();
+ $("<div class='inputs'></div>").appendTo( this.tool_body );
+ },
+
+ render : function() {
+ this.renderToolErrors();
+ this.$el.css( "width", Math.min(250, Math.max(this.$el.width(), this.output_width )));
+ },
+
+ renderToolErrors: function( ) {
+ if ( this.node.tool_errors ) {
+ this.$el.addClass( "tool-node-error" );
+ } else {
+ this.$el.removeClass( "tool-node-error" );
+ }
+ },
+
+ updateMaxWidth: function( newWidth ) {
+ this.output_width = Math.max( this.output_width, newWidth );
+ },
+
+ addRule: function() {
+ this.tool_body.append( $( "<div class='rule'></div>" ) );
+ },
+
+ addDataInput: function( inputView ) {
+ var ib = inputView.$el;
+ var terminalElement = inputView.terminalElement;
+ this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
+ }
+
+} );
+
+
+
+////////////
+// END VIEWS
+////////////
+
+
function Connector( handle1, handle2 ) {
this.canvas = null;
this.dragging = false;
@@ -295,7 +347,6 @@
$(element).removeClass( "toolForm-active" );
},
init_field_data : function ( data ) {
- var f = this.element;
if ( data.type ) {
this.type = data.type;
}
@@ -308,16 +359,12 @@
this.post_job_actions = data.post_job_actions ? data.post_job_actions : {};
this.workflow_outputs = data.workflow_outputs ? data.workflow_outputs : [];
- if ( this.tool_errors ) {
- f.addClass( "tool-node-error" );
- } else {
- f.removeClass( "tool-node-error" );
- }
var node = this;
- var output_width = Math.max(150, f.width());
- var b = f.find( ".toolFormBody" );
- b.find( "div" ).remove();
- var ibox = $("<div class='inputs'></div>").appendTo( b );
+ var nodeView = new NodeView({
+ el: this.element[ 0 ],
+ node: node,
+ });
+
$.each( data.data_inputs, function( i, input ) {
var t = node.new_input_terminal( input );
var ib = $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" );
@@ -335,7 +382,7 @@
ibox.append( ib.prepend( t ) );
});
if ( ( data.data_inputs.length > 0 ) && ( data.data_outputs.length > 0 ) ) {
- b.append( $( "<div class='rule'></div>" ) );
+ nodeView.addRule();
}
$.each( data.data_outputs, function( i, output ) {
var t = $( "<div class='terminal output-terminal'></div>" );
@@ -391,15 +438,15 @@
top: -1000,
display:'none'});
$('body').append(r);
- output_width = Math.max(output_width, r.outerWidth() + 17);
+ nodeView.updateMaxWidth( r.outerWidth() + 17 );
r.css({ position:'',
left:'',
top:'',
display:'' });
r.detach();
- b.append( r.append( t ) );
+ nodeView.tool_body.append( r.append( t ) );
});
- f.css( "width", Math.min(250, Math.max(f.width(), output_width )));
+ nodeView.render();
workflow.node_changed( this );
},
update_field_data : function( data ) {
diff -r 12e6db99d15193b700cbde74f31c71a2ef9bcc2d -r 24539736d9331e3586a2e9cc32ee31da43105900 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -376,4 +376,41 @@
} );
} );
+ /* global NodeView */
+ module( "Node view ", {
+ setup: function() {
+ this.set_for_node( {} );
+ },
+ set_for_node: function( node ) {
+ var element = $("<div>");
+ this.view = new NodeView( { node: node, el: element[ 0 ] } );
+ },
+ } );
+
+ test( "tool error styling", function() {
+ this.set_for_node( { tool_errors: false } );
+ this.view.render();
+ ok( ! this.view.$el.hasClass( "tool-node-error" ) );
+ this.set_for_node( { tool_errors: true } );
+ this.view.render();
+ ok( this.view.$el.hasClass( "tool-node-error" ) );
+ } );
+
+ test( "rendering correct width", function() {
+ // Default width is 150
+ this.view.render();
+ equal( this.view.$el.width(), 150 );
+
+ // If any data rows are greater, it will update
+ this.view.updateMaxWidth( 200 );
+ this.view.render();
+ equal( this.view.$el.width(), 200 );
+
+ // However 250 is the maximum width of node
+ this.view.updateMaxWidth( 300 );
+ this.view.render();
+ equal( this.view.$el.width(), 250 );
+
+ } );
+
});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/d43d2a1c14cb/
Changeset: d43d2a1c14cb
User: jmchilton
Date: 2014-04-10 22:46:06
Summary: Workflow editor backbonification - add DataInputView.
Affected #: 1 file
diff -r 24539736d9331e3586a2e9cc32ee31da43105900 -r d43d2a1c14cb8407c10a67af8400c4bf9a3236b8 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -115,6 +115,33 @@
+var DataInputView = Backbone.View.extend( {
+ className: "form-row dataRow input-data-row",
+
+ initialize: function( options ){
+ this.input = options.input;
+ this.nodeView = options.nodeView;
+ this.terminalElement = options.terminalElement;
+
+ this.$el.attr( "name", this.input.name )
+ .html( this.input.label )
+ .css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+
+ $('body').append(this.el);
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' });
+ this.$el.remove();
+ },
+
+} );
+
+
////////////
// END VIEWS
////////////
@@ -366,20 +393,12 @@
});
$.each( data.data_inputs, function( i, input ) {
- var t = node.new_input_terminal( input );
- var ib = $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" );
- ib.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append(ib);
- output_width = Math.max(output_width, ib.outerWidth());
- ib.css({ position:'',
- left:'',
- top:'',
- display:'' });
- ib.remove();
- ibox.append( ib.prepend( t ) );
+ var terminalElement = node.new_input_terminal( input );
+ nodeView.addDataInput( new DataInputView( {
+ "terminalElement": terminalElement,
+ "input": input,
+ "nodeView": nodeView
+ } ) );
});
if ( ( data.data_inputs.length > 0 ) && ( data.data_outputs.length > 0 ) ) {
nodeView.addRule();
https://bitbucket.org/galaxy/galaxy-central/commits/532e7490c35e/
Changeset: 532e7490c35e
User: jmchilton
Date: 2014-04-10 22:46:06
Summary: Workflow editor backbonification - add view for output callout.
Affected #: 1 file
diff -r d43d2a1c14cb8407c10a67af8400c4bf9a3236b8 -r 532e7490c35e6426572f38b5e288f1165baa4c1d static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -142,6 +142,60 @@
} );
+
+var OutputCalloutView = Backbone.View.extend( {
+ tagName: "div",
+
+ initialize: function( options ) {
+ this.label = options.label;
+ this.node = options.node;
+ this.output = options.output;
+
+ var view = this;
+ this.$el
+ .attr( "class", 'callout '+this.label )
+ .css( { display: 'none' } )
+ .append(
+ $("<div class='buttons'></div>").append(
+ $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
+ if ($.inArray(view.output.name, view.node.workflow_outputs) != -1){
+ view.node.workflow_outputs.splice($.inArray(view.output.name, view.node.workflow_outputs), 1);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ }else{
+ view.node.workflow_outputs.push(view.output.name);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ workflow.has_changes = true;
+ canvas_manager.draw_overview();
+ })))
+ .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
+
+ this.$el.css({
+ top: '50%',
+ margin:'-8px 0px 0px 0px',
+ right: 8
+ });
+ this.$el.show();
+ this.resetImage();
+ },
+
+ resetImage: function() {
+ if ($.inArray( this.output.name, this.node.workflow_outputs) === -1){
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ } else{
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ },
+
+ hoverImage: function() {
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
+ }
+
+} );
+
+
+
+
////////////
// END VIEWS
////////////
@@ -412,45 +466,13 @@
}
var r = $("<div class='form-row dataRow'>" + label + "</div>" );
if (node.type == 'tool'){
- var callout = $("<div class='callout "+label+"'></div>")
- .css( { display: 'none' } )
- .append(
- $("<div class='buttons'></div>").append(
- $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
- if ($.inArray(output.name, node.workflow_outputs) != -1){
- node.workflow_outputs.splice($.inArray(output.name, node.workflow_outputs), 1);
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- node.workflow_outputs.push(output.name);
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- workflow.has_changes = true;
- canvas_manager.draw_overview();
- })))
- .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
- callout.css({
- top: '50%',
- margin:'-8px 0px 0px 0px',
- right: 8
- });
- callout.show();
- r.append(callout);
- if ($.inArray(output.name, node.workflow_outputs) === -1){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- r.hover(
- function(){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
- },
- function(){
- if ($.inArray(output.name, node.workflow_outputs) === -1){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- });
+ var calloutView = new OutputCalloutView( {
+ "label": label,
+ "output": output,
+ "node": node,
+ });
+ r.append( calloutView.el );
+ r.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
}
r.css({ position:'absolute',
left: -1000,
https://bitbucket.org/galaxy/galaxy-central/commits/6a62178693eb/
Changeset: 6a62178693eb
User: jmchilton
Date: 2014-04-10 22:46:06
Summary: Workflow editor backbonification - add view for output data view.
Affected #: 1 file
diff -r 532e7490c35e6426572f38b5e288f1165baa4c1d -r 6a62178693eb664344262fd12e147fb5696a185e static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -109,6 +109,10 @@
var ib = inputView.$el;
var terminalElement = inputView.terminalElement;
this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
+ },
+
+ addDataOutput: function( outputView ) {
+ this.tool_body.append( outputView.$el.append( outputView.terminalElement ) );
}
} );
@@ -196,6 +200,48 @@
+var DataOutputView = Backbone.View.extend( {
+ className: "form-row dataRow",
+
+ initialize: function( options ) {
+ this.output = options.output;
+ this.terminalElement = options.terminalElement;
+ this.nodeView = options.nodeView;
+
+ var output = this.output;
+ var label = output.name;
+ var node = this.nodeView.node;
+ if ( output.extensions.indexOf( 'input' ) < 0 ) {
+ label = label + " (" + output.extensions.join(", ") + ")";
+ }
+ this.$el.html( label )
+
+ if (node.type == 'tool'){
+ var calloutView = new OutputCalloutView( {
+ "label": label,
+ "output": output,
+ "node": node,
+ });
+ this.$el.append( calloutView.el );
+ this.$el.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
+ }
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+ $('body').append( this.el );
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() + 17 );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' })
+ .detach();
+ }
+
+} );
+
+
+
////////////
// END VIEWS
////////////
@@ -458,34 +504,13 @@
nodeView.addRule();
}
$.each( data.data_outputs, function( i, output ) {
- var t = $( "<div class='terminal output-terminal'></div>" );
- node.enable_output_terminal( t[ 0 ], output.name, output.extensions );
- var label = output.name;
- if ( output.extensions.indexOf( 'input' ) < 0 ) {
- label = label + " (" + output.extensions.join(", ") + ")";
- }
- var r = $("<div class='form-row dataRow'>" + label + "</div>" );
- if (node.type == 'tool'){
- var calloutView = new OutputCalloutView( {
- "label": label,
- "output": output,
- "node": node,
- });
- r.append( calloutView.el );
- r.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
- }
- r.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append(r);
- nodeView.updateMaxWidth( r.outerWidth() + 17 );
- r.css({ position:'',
- left:'',
- top:'',
- display:'' });
- r.detach();
- nodeView.tool_body.append( r.append( t ) );
+ var terminalElement = $( "<div class='terminal output-terminal'></div>" );
+ node.enable_output_terminal( terminalElement[ 0 ], output.name, output.extensions );
+ nodeView.addDataOutput( new DataOutputView( {
+ "output": output,
+ "terminalElement": terminalElement,
+ "nodeView": nodeView,
+ } ) );
});
nodeView.render();
workflow.node_changed( this );
https://bitbucket.org/galaxy/galaxy-central/commits/00cfe74bb2af/
Changeset: 00cfe74bb2af
User: jmchilton
Date: 2014-04-10 22:46:06
Summary: Workflow editor backbonification - add InputTerminalView.
Add unit tests for new view.
Affected #: 2 files
diff -r 6a62178693eb664344262fd12e147fb5696a185e -r 00cfe74bb2afee051f62859fe9ae4b49327ec097 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -242,6 +242,72 @@
+var InputTerminalView = Backbone.View.extend( {
+ className: "terminal input-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var input = options.input;
+
+ var name = input.name;
+ var types = input.extensions;
+ var multiple = input.multiple;
+
+ var element = this.el;
+
+ var terminal = element.terminal = new InputTerminal( element, types, multiple );
+ terminal.node = node;
+ terminal.name = name;
+ $(element).bind( "dropinit", function( e, d ) {
+ // Accept a dragable if it is an output terminal and has a
+ // compatible type
+ return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
+ }).bind( "dropstart", function( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
+ }
+ }).bind( "dropend", function ( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
+ }
+ }).bind( "drop", function( e, d ) {
+ ( new Connector( d.drag.terminal, terminal ) ).redraw();
+ }).bind( "hover", function() {
+ // If connected, create a popup to allow disconnection
+ if ( terminal.connectors.length > 0 ) {
+ // Create callout
+ var t = $("<div class='callout'></div>")
+ .css( { display: 'none' } )
+ .appendTo( "body" )
+ .append(
+ $("<div class='button'></div>").append(
+ $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
+ $.each( terminal.connectors, function( _, x ) {
+ if (x) {
+ x.destroy();
+ }
+ });
+ t.remove();
+ })))
+ .bind( "mouseleave", function() {
+ $(this).remove();
+ });
+ // Position it and show
+ t.css({
+ top: $(element).offset().top - 2,
+ left: $(element).offset().left - t.width(),
+ 'padding-right': $(element).width()
+ }).show();
+ }
+ });
+
+ node.input_terminals[name] = terminal;
+ },
+} );
+
+
+
+
////////////
// END VIEWS
////////////
@@ -350,61 +416,6 @@
this.tool_errors = {};
}
$.extend( Node.prototype, {
- new_input_terminal : function( input ) {
- var t = $("<div class='terminal input-terminal'></div>")[ 0 ];
- this.enable_input_terminal( t, input.name, input.extensions, input.multiple );
- return t;
- },
- enable_input_terminal : function( element, name, types, multiple ) {
- var node = this;
-
- var terminal = element.terminal = new InputTerminal( element, types, multiple );
- terminal.node = node;
- terminal.name = name;
- $(element).bind( "dropinit", function( e, d ) {
- // Accept a dragable if it is an output terminal and has a
- // compatible type
- return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
- }).bind( "dropstart", function( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
- }
- }).bind( "dropend", function ( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
- }
- }).bind( "drop", function( e, d ) {
- ( new Connector( d.drag.terminal, terminal ) ).redraw();
- }).bind( "hover", function() {
- // If connected, create a popup to allow disconnection
- if ( terminal.connectors.length > 0 ) {
- // Create callout
- var t = $("<div class='callout'></div>")
- .css( { display: 'none' } )
- .appendTo( "body" )
- .append(
- $("<div class='button'></div>").append(
- $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
- $.each( terminal.connectors, function( _, x ) {
- if (x) {
- x.destroy();
- }
- });
- t.remove();
- })))
- .bind( "mouseleave", function() {
- $(this).remove();
- });
- // Position it and show
- t.css({
- top: $(element).offset().top - 2,
- left: $(element).offset().left - t.width(),
- 'padding-right': $(element).width()
- }).show();
- }
- });
- node.input_terminals[name] = terminal;
- },
enable_output_terminal : function( element, name, type ) {
var node = this;
var terminal_element = element;
@@ -493,7 +504,11 @@
});
$.each( data.data_inputs, function( i, input ) {
- var terminalElement = node.new_input_terminal( input );
+ var terminalView = new InputTerminalView( {
+ node: node,
+ input: input
+ } );
+ var terminalElement = terminalView.el;
nodeView.addDataInput( new DataInputView( {
"terminalElement": terminalElement,
"input": input,
@@ -533,7 +548,12 @@
var old_body = el.find( "div.inputs" );
var new_body = $("<div class='inputs'></div>");
$.each( data.data_inputs, function( i, input ) {
- var t = node.new_input_terminal( input );
+ var terminalView = new InputTerminalView( {
+ node: node,
+ input: input
+ } );
+ var t = terminalView.el;
+
// If already connected save old connection
old_body.find( "div[name='" + input.name + "']" ).each( function() {
$(this).find( ".input-terminal" ).each( function() {
diff -r 6a62178693eb664344262fd12e147fb5696a185e -r 00cfe74bb2afee051f62859fe9ae4b49327ec097 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -413,4 +413,30 @@
} );
+ /* global InputTerminalView */
+ module( "Input terminal view", {
+ setup: function() {
+ this.node = { input_terminals: [] };
+ this.input = { name: "i1", extensions: "txt", multiple: false };
+ this.view = new InputTerminalView( {
+ node: this.node,
+ input: this.input,
+ });
+ }
+ } );
+
+ test( "terminal added to node", function() {
+ ok( this.node.input_terminals.i1 );
+ equal( this.node.input_terminals.i1.datatypes, [ "txt" ] );
+ equal( this.node.input_terminals.i1.multiple, false );
+ } );
+
+ test( "terminal element", function() {
+ var el = this.view.el;
+ equal( el.tagName, "DIV" );
+ equal( el.className, "terminal input-terminal");
+ } );
+
+ // TODO: Test binding... not sure how to do that exactly..
+
});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/4ec192c78091/
Changeset: 4ec192c78091
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - add OutputTerminalView.
Add unit tests for OutputTerminalView.
Affected #: 2 files
diff -r 00cfe74bb2afee051f62859fe9ae4b49327ec097 -r 4ec192c78091ea3de586de05f2f0d9ccc1ec6c49 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -307,6 +307,57 @@
+var OutputTerminalView = Backbone.View.extend( {
+ className: "terminal output-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var output = options.output;
+ var name = output.name;
+ var type = output.extensions;
+
+ var element = this.el;
+ var terminal_element = element;
+ var terminal = element.terminal = new OutputTerminal( element, type );
+ terminal.node = node;
+ terminal.name = name;
+ $(element).bind( "dragstart", function( e, d ) {
+ $( d.available ).addClass( "input-terminal-active" );
+ // Save PJAs in the case of change datatype actions.
+ workflow.check_changes_in_active_form();
+ // Drag proxy div
+ var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
+ .appendTo( "#canvas-container" ).get(0);
+ // Terminal and connection to display noodle while dragging
+ h.terminal = new OutputTerminal( h );
+ var c = new Connector();
+ c.dragging = true;
+ c.connect( element.terminal, h.terminal );
+ return h;
+ }).bind( "drag", function ( e, d ) {
+ var onmove = function() {
+ var po = $(d.proxy).offsetParent().offset(),
+ x = d.offsetX - po.left,
+ y = d.offsetY - po.top;
+ $(d.proxy).css( { left: x, top: y } );
+ d.proxy.terminal.redraw();
+ // FIXME: global
+ canvas_manager.update_viewport_overlay();
+ };
+ onmove();
+ $("#canvas-container").get(0).scroll_panel.test( e, onmove );
+ }).bind( "dragend", function ( e, d ) {
+ d.proxy.terminal.connectors[0].destroy();
+ $(d.proxy).remove();
+ $( d.available ).removeClass( "input-terminal-active" );
+ $("#canvas-container").get(0).scroll_panel.stop();
+ });
+ node.output_terminals[name] = terminal;
+ }
+
+} );
+
+
////////////
// END VIEWS
@@ -416,45 +467,6 @@
this.tool_errors = {};
}
$.extend( Node.prototype, {
- enable_output_terminal : function( element, name, type ) {
- var node = this;
- var terminal_element = element;
- var terminal = element.terminal = new OutputTerminal( element, type );
- terminal.node = node;
- terminal.name = name;
- $(element).bind( "dragstart", function( e, d ) {
- $( d.available ).addClass( "input-terminal-active" );
- // Save PJAs in the case of change datatype actions.
- workflow.check_changes_in_active_form();
- // Drag proxy div
- var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
- .appendTo( "#canvas-container" ).get(0);
- // Terminal and connection to display noodle while dragging
- h.terminal = new OutputTerminal( h );
- var c = new Connector();
- c.dragging = true;
- c.connect( element.terminal, h.terminal );
- return h;
- }).bind( "drag", function ( e, d ) {
- var onmove = function() {
- var po = $(d.proxy).offsetParent().offset(),
- x = d.offsetX - po.left,
- y = d.offsetY - po.top;
- $(d.proxy).css( { left: x, top: y } );
- d.proxy.terminal.redraw();
- // FIXME: global
- canvas_manager.update_viewport_overlay();
- };
- onmove();
- $("#canvas-container").get(0).scroll_panel.test( e, onmove );
- }).bind( "dragend", function ( e, d ) {
- d.proxy.terminal.connectors[0].destroy();
- $(d.proxy).remove();
- $( d.available ).removeClass( "input-terminal-active" );
- $("#canvas-container").get(0).scroll_panel.stop();
- });
- node.output_terminals[name] = terminal;
- },
redraw : function () {
$.each( this.input_terminals, function( _, t ) {
t.redraw();
@@ -519,11 +531,13 @@
nodeView.addRule();
}
$.each( data.data_outputs, function( i, output ) {
- var terminalElement = $( "<div class='terminal output-terminal'></div>" );
- node.enable_output_terminal( terminalElement[ 0 ], output.name, output.extensions );
+ var terminalView = new OutputTerminalView( {
+ node: node,
+ output: output
+ } );
nodeView.addDataOutput( new DataOutputView( {
"output": output,
- "terminalElement": terminalElement,
+ "terminalElement": terminalView.el,
"nodeView": nodeView,
} ) );
});
diff -r 00cfe74bb2afee051f62859fe9ae4b49327ec097 -r 4ec192c78091ea3de586de05f2f0d9ccc1ec6c49 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -439,4 +439,29 @@
// TODO: Test binding... not sure how to do that exactly..
+ /* global OutputTerminalView */
+ module( "Output terminal view", {
+ setup: function() {
+ this.node = { output_terminals: [] };
+ this.output = { name: "o1", extensions: "txt" };
+ this.view = new OutputTerminalView( {
+ node: this.node,
+ output: this.output,
+ });
+ }
+ } );
+
+ test( "terminal added to node", function() {
+ ok( this.node.output_terminals.o1 );
+ equal( this.node.output_terminals.o1.datatypes, [ "txt" ] );
+ } );
+
+ test( "terminal element", function() {
+ var el = this.view.el;
+ equal( el.tagName, "DIV" );
+ equal( el.className, "terminal output-terminal");
+ } );
+
+ // TODO: Test bindings
+
});
\ No newline at end of file
https://bitbucket.org/galaxy/galaxy-central/commits/0274e805ac70/
Changeset: 0274e805ac70
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - InputTerminalView to Backbone.View event binding.
Affected #: 1 file
diff -r 4ec192c78091ea3de586de05f2f0d9ccc1ec6c49 -r 0274e805ac700ae255c0ba8aa26a18ff48da08bd static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -253,56 +253,77 @@
var types = input.extensions;
var multiple = input.multiple;
- var element = this.el;
-
- var terminal = element.terminal = new InputTerminal( element, types, multiple );
+ var terminal = this.el.terminal = new InputTerminal( this.el, types, multiple );
terminal.node = node;
terminal.name = name;
- $(element).bind( "dropinit", function( e, d ) {
- // Accept a dragable if it is an output terminal and has a
- // compatible type
- return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
- }).bind( "dropstart", function( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
- }
- }).bind( "dropend", function ( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
- }
- }).bind( "drop", function( e, d ) {
- ( new Connector( d.drag.terminal, terminal ) ).redraw();
- }).bind( "hover", function() {
- // If connected, create a popup to allow disconnection
- if ( terminal.connectors.length > 0 ) {
- // Create callout
- var t = $("<div class='callout'></div>")
- .css( { display: 'none' } )
- .appendTo( "body" )
- .append(
- $("<div class='button'></div>").append(
- $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
- $.each( terminal.connectors, function( _, x ) {
- if (x) {
- x.destroy();
- }
- });
- t.remove();
- })))
- .bind( "mouseleave", function() {
- $(this).remove();
- });
- // Position it and show
- t.css({
- top: $(element).offset().top - 2,
- left: $(element).offset().left - t.width(),
- 'padding-right': $(element).width()
- }).show();
- }
- });
node.input_terminals[name] = terminal;
},
+
+ events: {
+ "dropinit": "onDropInit",
+ "dropstart": "onDropStart",
+ "dropend": "onDropEnd",
+ "drop": "onDrop",
+ "hover": "onHover",
+ },
+
+ onDropInit: function( e, d ) {
+ var terminal = this.el.terminal;
+ // Accept a dragable if it is an output terminal and has a
+ // compatible type
+ return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
+ },
+
+ onDropStart: function( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
+ }
+ },
+
+ onDropEnd: function ( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
+ }
+ },
+
+ onDrop: function( e, d ) {
+ var terminal = this.el.terminal;
+ new Connector( d.drag.terminal, terminal ).redraw();
+ },
+
+ onHover: function() {
+ var element = this.el;
+ var terminal = element.terminal;
+
+ // If connected, create a popup to allow disconnection
+ if ( terminal.connectors.length > 0 ) {
+ // Create callout
+ var t = $("<div class='callout'></div>")
+ .css( { display: 'none' } )
+ .appendTo( "body" )
+ .append(
+ $("<div class='button'></div>").append(
+ $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
+ $.each( terminal.connectors, function( _, x ) {
+ if (x) {
+ x.destroy();
+ }
+ });
+ t.remove();
+ })))
+ .bind( "mouseleave", function() {
+ $(this).remove();
+ });
+ // Position it and show
+ t.css({
+ top: $(element).offset().top - 2,
+ left: $(element).offset().left - t.width(),
+ 'padding-right': $(element).width()
+ }).show();
+ }
+ },
+
} );
https://bitbucket.org/galaxy/galaxy-central/commits/63f7752b59fd/
Changeset: 63f7752b59fd
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - OutputTerminalView to Backbone.View event binding.
Affected #: 1 file
diff -r 0274e805ac700ae255c0ba8aa26a18ff48da08bd -r 63f7752b59fdc717330e4e9988fb8da18dde90b0 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -342,38 +342,49 @@
var terminal = element.terminal = new OutputTerminal( element, type );
terminal.node = node;
terminal.name = name;
- $(element).bind( "dragstart", function( e, d ) {
- $( d.available ).addClass( "input-terminal-active" );
- // Save PJAs in the case of change datatype actions.
- workflow.check_changes_in_active_form();
- // Drag proxy div
- var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
- .appendTo( "#canvas-container" ).get(0);
- // Terminal and connection to display noodle while dragging
- h.terminal = new OutputTerminal( h );
- var c = new Connector();
- c.dragging = true;
- c.connect( element.terminal, h.terminal );
- return h;
- }).bind( "drag", function ( e, d ) {
- var onmove = function() {
- var po = $(d.proxy).offsetParent().offset(),
- x = d.offsetX - po.left,
- y = d.offsetY - po.top;
- $(d.proxy).css( { left: x, top: y } );
- d.proxy.terminal.redraw();
- // FIXME: global
- canvas_manager.update_viewport_overlay();
- };
- onmove();
- $("#canvas-container").get(0).scroll_panel.test( e, onmove );
- }).bind( "dragend", function ( e, d ) {
- d.proxy.terminal.connectors[0].destroy();
- $(d.proxy).remove();
- $( d.available ).removeClass( "input-terminal-active" );
- $("#canvas-container").get(0).scroll_panel.stop();
- });
node.output_terminals[name] = terminal;
+ },
+
+ events: {
+ "drag": "onDrag",
+ "dragstart": "onDragStart",
+ "dragend": "onDragEnd",
+ },
+
+ onDrag: function ( e, d ) {
+ var onmove = function() {
+ var po = $(d.proxy).offsetParent().offset(),
+ x = d.offsetX - po.left,
+ y = d.offsetY - po.top;
+ $(d.proxy).css( { left: x, top: y } );
+ d.proxy.terminal.redraw();
+ // FIXME: global
+ canvas_manager.update_viewport_overlay();
+ };
+ onmove();
+ $("#canvas-container").get(0).scroll_panel.test( e, onmove );
+ },
+
+ onDragStart: function( e, d ) {
+ $( d.available ).addClass( "input-terminal-active" );
+ // Save PJAs in the case of change datatype actions.
+ workflow.check_changes_in_active_form();
+ // Drag proxy div
+ var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
+ .appendTo( "#canvas-container" ).get(0);
+ // Terminal and connection to display noodle while dragging
+ h.terminal = new OutputTerminal( h );
+ var c = new Connector();
+ c.dragging = true;
+ c.connect( this.el.terminal, h.terminal );
+ return h;
+ },
+
+ onDragEnd: function ( e, d ) {
+ d.proxy.terminal.connectors[0].destroy();
+ $(d.proxy).remove();
+ $( d.available ).removeClass( "input-terminal-active" );
+ $("#canvas-container").get(0).scroll_panel.stop();
}
} );
https://bitbucket.org/galaxy/galaxy-central/commits/a0e1c04f77ec/
Changeset: a0e1c04f77ec
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - move terminal presentation logic from NodeView to DataInputView.
Affected #: 1 file
diff -r 63f7752b59fdc717330e4e9988fb8da18dde90b0 -r a0e1c04f77ec7d5727a01c7ee2a79b8a88121968 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -105,7 +105,17 @@
this.tool_body.append( $( "<div class='rule'></div>" ) );
},
- addDataInput: function( inputView ) {
+ addDataInput: function( input ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var terminalElement = terminalView.el;
+ var inputView = new DataInputView( {
+ "terminalElement": terminalElement,
+ "input": input,
+ "nodeView": this,
+ } );
var ib = inputView.$el;
var terminalElement = inputView.terminalElement;
this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
@@ -548,16 +558,7 @@
});
$.each( data.data_inputs, function( i, input ) {
- var terminalView = new InputTerminalView( {
- node: node,
- input: input
- } );
- var terminalElement = terminalView.el;
- nodeView.addDataInput( new DataInputView( {
- "terminalElement": terminalElement,
- "input": input,
- "nodeView": nodeView
- } ) );
+ nodeView.addDataInput( input );
});
if ( ( data.data_inputs.length > 0 ) && ( data.data_outputs.length > 0 ) ) {
nodeView.addRule();
https://bitbucket.org/galaxy/galaxy-central/commits/8facb774346b/
Changeset: 8facb774346b
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - move terminal presentation logic from NodeView to DataOutputView.
Affected #: 1 file
diff -r a0e1c04f77ec7d5727a01c7ee2a79b8a88121968 -r 8facb774346bb47abd7adb929394bf2b54eb5657 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -121,7 +121,16 @@
this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
},
- addDataOutput: function( outputView ) {
+ addDataOutput: function( output ) {
+ var terminalView = new OutputTerminalView( {
+ node: this.node,
+ output: output
+ } );
+ var outputView = new DataOutputView( {
+ "output": output,
+ "terminalElement": terminalView.el,
+ "nodeView": this,
+ } );
this.tool_body.append( outputView.$el.append( outputView.terminalElement ) );
}
@@ -564,16 +573,8 @@
nodeView.addRule();
}
$.each( data.data_outputs, function( i, output ) {
- var terminalView = new OutputTerminalView( {
- node: node,
- output: output
- } );
- nodeView.addDataOutput( new DataOutputView( {
- "output": output,
- "terminalElement": terminalView.el,
- "nodeView": nodeView,
- } ) );
- });
+ nodeView.addDataOutput( output );
+ } );
nodeView.render();
workflow.node_changed( this );
},
https://bitbucket.org/galaxy/galaxy-central/commits/118962ee000a/
Changeset: 118962ee000a
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - refactor some update_field_data presentation logic into NodeView.
Affected #: 1 file
diff -r 8facb774346bb47abd7adb929394bf2b54eb5657 -r 118962ee000a5337d2c1503c7bdb8d526ad7a7e7 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -81,7 +81,7 @@
this.output_width = Math.max(150, this.$el.width());
this.tool_body = this.$el.find( ".toolFormBody" );
this.tool_body.find( "div" ).remove();
- $("<div class='inputs'></div>").appendTo( this.tool_body );
+ this.newInputsDiv().appendTo( this.tool_body );
},
render : function() {
@@ -97,6 +97,10 @@
}
},
+ newInputsDiv: function() {
+ return $("<div class='inputs'></div>");
+ },
+
updateMaxWidth: function( newWidth ) {
this.output_width = Math.max( this.output_width, newWidth );
},
@@ -121,6 +125,37 @@
this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
},
+ replaceDataInput: function( input, new_body ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var t = terminalView.el;
+
+ // If already connected save old connection
+ this.$( "div[name='" + input.name + "']" ).each( function() {
+ $(this).find( ".input-terminal" ).each( function() {
+ var c = this.terminal.connectors[0];
+ if ( c ) {
+ t.terminal.connectors[0] = c;
+ c.handle2 = t.terminal;
+ }
+ });
+ $(this).remove();
+ });
+ var inputView = new DataInputView( {
+ "terminalElement": t,
+ "input": input,
+ "nodeView": this,
+ "skipResize": true,
+ } );
+ var ib = inputView.$el;
+
+ // Append to new body
+ new_body.append( ib.prepend( t ) );
+
+ },
+
addDataOutput: function( output ) {
var terminalView = new OutputTerminalView( {
node: this.node,
@@ -147,19 +182,21 @@
this.terminalElement = options.terminalElement;
this.$el.attr( "name", this.input.name )
- .html( this.input.label )
- .css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
-
+ .html( this.input.label );
+
+ if( ! options.skipResize ) {
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
$('body').append(this.el);
- this.nodeView.updateMaxWidth( this.$el.outerWidth() );
- this.$el.css({ position:'',
- left:'',
- top:'',
- display:'' });
- this.$el.remove();
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' });
+ this.$el.remove();
+ }
},
} );
@@ -565,6 +602,7 @@
el: this.element[ 0 ],
node: node,
});
+ node.nodeView = nodeView;
$.each( data.data_inputs, function( i, input ) {
nodeView.addDataInput( input );
@@ -579,42 +617,20 @@
workflow.node_changed( this );
},
update_field_data : function( data ) {
- var el = $(this.element),
- node = this;
+ var node = this;
+ nodeView = node.nodeView;
this.tool_state = data.tool_state;
this.form_html = data.form_html;
this.tool_errors = data.tool_errors;
this.annotation = data['annotation'];
var pja_in = $.parseJSON(data.post_job_actions);
this.post_job_actions = pja_in ? pja_in : {};
- if ( this.tool_errors ) {
- el.addClass( "tool-node-error" );
- } else {
- el.removeClass( "tool-node-error" );
- }
+ node.nodeView.renderToolErrors();
// Update input rows
- var old_body = el.find( "div.inputs" );
- var new_body = $("<div class='inputs'></div>");
+ var old_body = nodeView.$( "div.inputs" );
+ var new_body = nodeView.newInputsDiv();
$.each( data.data_inputs, function( i, input ) {
- var terminalView = new InputTerminalView( {
- node: node,
- input: input
- } );
- var t = terminalView.el;
-
- // If already connected save old connection
- old_body.find( "div[name='" + input.name + "']" ).each( function() {
- $(this).find( ".input-terminal" ).each( function() {
- var c = this.terminal.connectors[0];
- if ( c ) {
- t.terminal.connectors[0] = c;
- c.handle2 = t.terminal;
- }
- });
- $(this).remove();
- });
- // Append to new body
- new_body.append( $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" ).prepend( t ) );
+ node.nodeView.replaceDataInput( input, new_body );
});
old_body.replaceWith( new_body );
// Cleanup any leftover terminals
https://bitbucket.org/galaxy/galaxy-central/commits/61b3c6c4be0e/
Changeset: 61b3c6c4be0e
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - make Node a model.
Affected #: 2 files
diff -r 118962ee000a5337d2c1503c7bdb8d526ad7a7e7 -r 61b3c6c4be0e1c8d02ef9073d294b61db461f4b3 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -6,13 +6,13 @@
connect: function ( connector ) {
this.connectors.push( connector );
if ( this.node ) {
- this.node.changed();
+ this.node.markChanged();
}
},
disconnect: function ( connector ) {
this.connectors.splice( $.inArray( connector, this.connectors ), 1 );
if ( this.node ) {
- this.node.changed();
+ this.node.markChanged();
}
},
redraw: function () {
@@ -548,13 +548,14 @@
}
} );
-function Node( element ) {
- this.element = element;
- this.input_terminals = {};
- this.output_terminals = {};
- this.tool_errors = {};
-}
-$.extend( Node.prototype, {
+var Node = Backbone.Model.extend({
+
+ initialize: function( attr ) {
+ this.element = attr.element;
+ this.input_terminals = {};
+ this.output_terminals = {};
+ this.tool_errors = {};
+ },
redraw : function () {
$.each( this.input_terminals, function( _, t ) {
t.redraw();
@@ -638,7 +639,7 @@
this.terminal.destroy();
});
// If active, reactivate with new form_html
- this.changed();
+ this.markChanged();
this.redraw();
},
error : function ( text ) {
@@ -649,7 +650,7 @@
b.html( tmp );
workflow.node_changed( this );
},
- changed: function() {
+ markChanged: function() {
workflow.node_changed( this );
}
} );
@@ -1034,7 +1035,7 @@
function prebuild_node( type, title_text, tool_id ) {
var f = $("<div class='toolForm toolFormInCanvas'></div>");
- var node = new Node( f );
+ var node = new Node( { element: f } );
node.type = type;
if ( type == 'tool' ) {
node.tool_id = tool_id;
diff -r 118962ee000a5337d2c1503c7bdb8d526ad7a7e7 -r 61b3c6c4be0e1c8d02ef9073d294b61db461f4b3 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -81,25 +81,25 @@
} );
test( "test connect", function() {
- this.node.changed = sinon.spy();
+ this.node.markChanged = sinon.spy();
var connector = {};
this.input_terminal.connect( connector );
- // Assert node changed called
- ok( this.node.changed.called );
+ // Assert node markChanged called
+ ok( this.node.markChanged.called );
// Assert connectors updated
ok( this.input_terminal.connectors[ 0 ] === connector );
} );
test( "test disconnect", function() {
- this.node.changed = sinon.spy();
+ this.node.markChanged = sinon.spy();
var connector = this.test_connector( {} );
this.input_terminal.disconnect( connector );
- // Assert node changed called
- ok( this.node.changed.called );
+ // Assert node markChanged called
+ ok( this.node.markChanged.called );
// Assert connectors updated
equal( this.input_terminal.connectors.length, 0 );
} );
@@ -204,7 +204,7 @@
this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.element = $("<div><div class='toolFormBody'></div></div>");
- this.node = new Node( this.element );
+ this.node = new Node( { element: this.element } );
this.node.input_terminals.i1 = this.input_terminal;
this.node.output_terminals.o1 = this.output_terminal;
},
https://bitbucket.org/galaxy/galaxy-central/commits/4957c7b9a709/
Changeset: 4957c7b9a709
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - make Terminal classes into models.
Affected #: 2 files
diff -r 61b3c6c4be0e1c8d02ef9073d294b61db461f4b3 -r 4957c7b9a70979fa10f85619ad608b071827df66 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -1,8 +1,8 @@
-function Terminal( element ) {
- this.element = element;
- this.connectors = [];
-}
-$.extend( Terminal.prototype, {
+var Terminal = Backbone.Model.extend( {
+ initialize: function( attr ) {
+ this.element = attr.element;
+ this.connectors = [];
+ },
connect: function ( connector ) {
this.connectors.push( connector );
if ( this.node ) {
@@ -25,48 +25,14 @@
c.destroy();
});
}
-});
+} );
-function OutputTerminal( element, datatypes ) {
- Terminal.call( this, element );
- this.datatypes = datatypes;
-}
-
-OutputTerminal.prototype = new Terminal();
-
-function InputTerminal( element, datatypes, multiple ) {
- Terminal.call( this, element );
- this.datatypes = datatypes;
- this.multiple = multiple
-}
-
-InputTerminal.prototype = new Terminal();
-
-$.extend( InputTerminal.prototype, {
- can_accept: function ( other ) {
- if ( this.connectors.length < 1 || this.multiple) {
- for ( var t in this.datatypes ) {
- var cat_outputs = new Array();
- cat_outputs = cat_outputs.concat(other.datatypes);
- if (other.node.post_job_actions){
- for (var pja_i in other.node.post_job_actions){
- var pja = other.node.post_job_actions[pja_i];
- if (pja.action_type == "ChangeDatatypeAction" && (pja.output_name == '' || pja.output_name == other.name) && pja.action_arguments){
- cat_outputs.push(pja.action_arguments['newtype']);
- }
- }
- }
- // FIXME: No idea what to do about case when datatype is 'input'
- for ( var other_datatype_i in cat_outputs ) {
- if ( cat_outputs[other_datatype_i] == "input" || issubtype( cat_outputs[other_datatype_i], this.datatypes[t] ) ) {
- return true;
- }
- }
- }
- }
- return false;
+var OutputTerminal = Terminal.extend( {
+ initialize: function( attr ) {
+ Terminal.prototype.initialize.call( this, attr );
+ this.datatypes = attr.datatypes;
}
-});
+} );
//////////////
@@ -309,7 +275,7 @@
var types = input.extensions;
var multiple = input.multiple;
- var terminal = this.el.terminal = new InputTerminal( this.el, types, multiple );
+ var terminal = this.el.terminal = new InputTerminal( { element: this.el, datatypes: types, multiple: multiple } );
terminal.node = node;
terminal.name = name;
@@ -395,7 +361,7 @@
var element = this.el;
var terminal_element = element;
- var terminal = element.terminal = new OutputTerminal( element, type );
+ var terminal = element.terminal = new OutputTerminal( {element: element, datatypes: type } );
terminal.node = node;
terminal.name = name;
node.output_terminals[name] = terminal;
@@ -429,7 +395,7 @@
var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
.appendTo( "#canvas-container" ).get(0);
// Terminal and connection to display noodle while dragging
- h.terminal = new OutputTerminal( h );
+ h.terminal = new OutputTerminal( { element: h } );
var c = new Connector();
c.dragging = true;
c.connect( this.el.terminal, h.terminal );
@@ -452,6 +418,40 @@
////////////
+
+var InputTerminal = Terminal.extend( {
+ initialize: function( attr ) {
+ Terminal.prototype.initialize.call( this, attr );
+ this.datatypes = attr.datatypes;
+ this.multiple = attr.multiple;
+ },
+ can_accept: function ( other ) {
+ if ( this.connectors.length < 1 || this.multiple) {
+ for ( var t in this.datatypes ) {
+ var cat_outputs = new Array();
+ cat_outputs = cat_outputs.concat(other.datatypes);
+ if (other.node.post_job_actions){
+ for (var pja_i in other.node.post_job_actions){
+ var pja = other.node.post_job_actions[pja_i];
+ if (pja.action_type == "ChangeDatatypeAction" && (pja.output_name == '' || pja.output_name == other.name) && pja.action_arguments){
+ cat_outputs.push(pja.action_arguments['newtype']);
+ }
+ }
+ }
+ // FIXME: No idea what to do about case when datatype is 'input'
+ for ( var other_datatype_i in cat_outputs ) {
+ if ( cat_outputs[other_datatype_i] == "input" || issubtype( cat_outputs[other_datatype_i], this.datatypes[t] ) ) {
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+ }
+});
+
+
+
function Connector( handle1, handle2 ) {
this.canvas = null;
this.dragging = false;
diff -r 61b3c6c4be0e1c8d02ef9073d294b61db461f4b3 -r 4957c7b9a70979fa10f85619ad608b071827df66 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -58,7 +58,7 @@
setup: function() {
this.node = { };
this.element = $( "<div>" );
- this.input_terminal = new InputTerminal( this.element, [ "txt" ] );
+ this.input_terminal = new InputTerminal( { element: this.element, datatypes: [ "txt" ] } );
this.input_terminal.node = this.node;
},
test_connector: function( attr ) {
https://bitbucket.org/galaxy/galaxy-central/commits/f94426190a7b/
Changeset: f94426190a7b
User: jmchilton
Date: 2014-04-10 22:46:07
Summary: Workflow editor backbonification - reposition views to more appropriate part of file.
Affected #: 1 file
diff -r 4957c7b9a70979fa10f85619ad608b071827df66 -r f94426190a7b11837597efcf597aac288ae2dfe5 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -35,390 +35,6 @@
} );
-//////////////
-// START VIEWS
-//////////////
-
-
-
-var NodeView = Backbone.View.extend( {
- initialize: function( options ){
- this.node = options.node;
- this.output_width = Math.max(150, this.$el.width());
- this.tool_body = this.$el.find( ".toolFormBody" );
- this.tool_body.find( "div" ).remove();
- this.newInputsDiv().appendTo( this.tool_body );
- },
-
- render : function() {
- this.renderToolErrors();
- this.$el.css( "width", Math.min(250, Math.max(this.$el.width(), this.output_width )));
- },
-
- renderToolErrors: function( ) {
- if ( this.node.tool_errors ) {
- this.$el.addClass( "tool-node-error" );
- } else {
- this.$el.removeClass( "tool-node-error" );
- }
- },
-
- newInputsDiv: function() {
- return $("<div class='inputs'></div>");
- },
-
- updateMaxWidth: function( newWidth ) {
- this.output_width = Math.max( this.output_width, newWidth );
- },
-
- addRule: function() {
- this.tool_body.append( $( "<div class='rule'></div>" ) );
- },
-
- addDataInput: function( input ) {
- var terminalView = new InputTerminalView( {
- node: this.node,
- input: input
- } );
- var terminalElement = terminalView.el;
- var inputView = new DataInputView( {
- "terminalElement": terminalElement,
- "input": input,
- "nodeView": this,
- } );
- var ib = inputView.$el;
- var terminalElement = inputView.terminalElement;
- this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
- },
-
- replaceDataInput: function( input, new_body ) {
- var terminalView = new InputTerminalView( {
- node: this.node,
- input: input
- } );
- var t = terminalView.el;
-
- // If already connected save old connection
- this.$( "div[name='" + input.name + "']" ).each( function() {
- $(this).find( ".input-terminal" ).each( function() {
- var c = this.terminal.connectors[0];
- if ( c ) {
- t.terminal.connectors[0] = c;
- c.handle2 = t.terminal;
- }
- });
- $(this).remove();
- });
- var inputView = new DataInputView( {
- "terminalElement": t,
- "input": input,
- "nodeView": this,
- "skipResize": true,
- } );
- var ib = inputView.$el;
-
- // Append to new body
- new_body.append( ib.prepend( t ) );
-
- },
-
- addDataOutput: function( output ) {
- var terminalView = new OutputTerminalView( {
- node: this.node,
- output: output
- } );
- var outputView = new DataOutputView( {
- "output": output,
- "terminalElement": terminalView.el,
- "nodeView": this,
- } );
- this.tool_body.append( outputView.$el.append( outputView.terminalElement ) );
- }
-
-} );
-
-
-
-var DataInputView = Backbone.View.extend( {
- className: "form-row dataRow input-data-row",
-
- initialize: function( options ){
- this.input = options.input;
- this.nodeView = options.nodeView;
- this.terminalElement = options.terminalElement;
-
- this.$el.attr( "name", this.input.name )
- .html( this.input.label );
-
- if( ! options.skipResize ) {
- this.$el.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append(this.el);
- this.nodeView.updateMaxWidth( this.$el.outerWidth() );
- this.$el.css({ position:'',
- left:'',
- top:'',
- display:'' });
- this.$el.remove();
- }
- },
-
-} );
-
-
-
-var OutputCalloutView = Backbone.View.extend( {
- tagName: "div",
-
- initialize: function( options ) {
- this.label = options.label;
- this.node = options.node;
- this.output = options.output;
-
- var view = this;
- this.$el
- .attr( "class", 'callout '+this.label )
- .css( { display: 'none' } )
- .append(
- $("<div class='buttons'></div>").append(
- $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
- if ($.inArray(view.output.name, view.node.workflow_outputs) != -1){
- view.node.workflow_outputs.splice($.inArray(view.output.name, view.node.workflow_outputs), 1);
- view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- view.node.workflow_outputs.push(view.output.name);
- view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- workflow.has_changes = true;
- canvas_manager.draw_overview();
- })))
- .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
-
- this.$el.css({
- top: '50%',
- margin:'-8px 0px 0px 0px',
- right: 8
- });
- this.$el.show();
- this.resetImage();
- },
-
- resetImage: function() {
- if ($.inArray( this.output.name, this.node.workflow_outputs) === -1){
- this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- } else{
- this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- },
-
- hoverImage: function() {
- this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
- }
-
-} );
-
-
-
-
-var DataOutputView = Backbone.View.extend( {
- className: "form-row dataRow",
-
- initialize: function( options ) {
- this.output = options.output;
- this.terminalElement = options.terminalElement;
- this.nodeView = options.nodeView;
-
- var output = this.output;
- var label = output.name;
- var node = this.nodeView.node;
- if ( output.extensions.indexOf( 'input' ) < 0 ) {
- label = label + " (" + output.extensions.join(", ") + ")";
- }
- this.$el.html( label )
-
- if (node.type == 'tool'){
- var calloutView = new OutputCalloutView( {
- "label": label,
- "output": output,
- "node": node,
- });
- this.$el.append( calloutView.el );
- this.$el.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
- }
- this.$el.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append( this.el );
- this.nodeView.updateMaxWidth( this.$el.outerWidth() + 17 );
- this.$el.css({ position:'',
- left:'',
- top:'',
- display:'' })
- .detach();
- }
-
-} );
-
-
-
-var InputTerminalView = Backbone.View.extend( {
- className: "terminal input-terminal",
-
- initialize: function( options ) {
- var node = options.node;
- var input = options.input;
-
- var name = input.name;
- var types = input.extensions;
- var multiple = input.multiple;
-
- var terminal = this.el.terminal = new InputTerminal( { element: this.el, datatypes: types, multiple: multiple } );
- terminal.node = node;
- terminal.name = name;
-
- node.input_terminals[name] = terminal;
- },
-
- events: {
- "dropinit": "onDropInit",
- "dropstart": "onDropStart",
- "dropend": "onDropEnd",
- "drop": "onDrop",
- "hover": "onHover",
- },
-
- onDropInit: function( e, d ) {
- var terminal = this.el.terminal;
- // Accept a dragable if it is an output terminal and has a
- // compatible type
- return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
- },
-
- onDropStart: function( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
- }
- },
-
- onDropEnd: function ( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
- }
- },
-
- onDrop: function( e, d ) {
- var terminal = this.el.terminal;
- new Connector( d.drag.terminal, terminal ).redraw();
- },
-
- onHover: function() {
- var element = this.el;
- var terminal = element.terminal;
-
- // If connected, create a popup to allow disconnection
- if ( terminal.connectors.length > 0 ) {
- // Create callout
- var t = $("<div class='callout'></div>")
- .css( { display: 'none' } )
- .appendTo( "body" )
- .append(
- $("<div class='button'></div>").append(
- $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
- $.each( terminal.connectors, function( _, x ) {
- if (x) {
- x.destroy();
- }
- });
- t.remove();
- })))
- .bind( "mouseleave", function() {
- $(this).remove();
- });
- // Position it and show
- t.css({
- top: $(element).offset().top - 2,
- left: $(element).offset().left - t.width(),
- 'padding-right': $(element).width()
- }).show();
- }
- },
-
-} );
-
-
-
-var OutputTerminalView = Backbone.View.extend( {
- className: "terminal output-terminal",
-
- initialize: function( options ) {
- var node = options.node;
- var output = options.output;
- var name = output.name;
- var type = output.extensions;
-
- var element = this.el;
- var terminal_element = element;
- var terminal = element.terminal = new OutputTerminal( {element: element, datatypes: type } );
- terminal.node = node;
- terminal.name = name;
- node.output_terminals[name] = terminal;
- },
-
- events: {
- "drag": "onDrag",
- "dragstart": "onDragStart",
- "dragend": "onDragEnd",
- },
-
- onDrag: function ( e, d ) {
- var onmove = function() {
- var po = $(d.proxy).offsetParent().offset(),
- x = d.offsetX - po.left,
- y = d.offsetY - po.top;
- $(d.proxy).css( { left: x, top: y } );
- d.proxy.terminal.redraw();
- // FIXME: global
- canvas_manager.update_viewport_overlay();
- };
- onmove();
- $("#canvas-container").get(0).scroll_panel.test( e, onmove );
- },
-
- onDragStart: function( e, d ) {
- $( d.available ).addClass( "input-terminal-active" );
- // Save PJAs in the case of change datatype actions.
- workflow.check_changes_in_active_form();
- // Drag proxy div
- var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
- .appendTo( "#canvas-container" ).get(0);
- // Terminal and connection to display noodle while dragging
- h.terminal = new OutputTerminal( { element: h } );
- var c = new Connector();
- c.dragging = true;
- c.connect( this.el.terminal, h.terminal );
- return h;
- },
-
- onDragEnd: function ( e, d ) {
- d.proxy.terminal.connectors[0].destroy();
- $(d.proxy).remove();
- $( d.available ).removeClass( "input-terminal-active" );
- $("#canvas-container").get(0).scroll_panel.stop();
- }
-
-} );
-
-
-
-////////////
-// END VIEWS
-////////////
-
-
-
var InputTerminal = Terminal.extend( {
initialize: function( attr ) {
Terminal.prototype.initialize.call( this, attr );
@@ -1114,6 +730,389 @@
type_to_type = data.class_to_classes;
}
+
+//////////////
+// START VIEWS
+//////////////
+
+
+var NodeView = Backbone.View.extend( {
+ initialize: function( options ){
+ this.node = options.node;
+ this.output_width = Math.max(150, this.$el.width());
+ this.tool_body = this.$el.find( ".toolFormBody" );
+ this.tool_body.find( "div" ).remove();
+ this.newInputsDiv().appendTo( this.tool_body );
+ },
+
+ render : function() {
+ this.renderToolErrors();
+ this.$el.css( "width", Math.min(250, Math.max(this.$el.width(), this.output_width )));
+ },
+
+ renderToolErrors: function( ) {
+ if ( this.node.tool_errors ) {
+ this.$el.addClass( "tool-node-error" );
+ } else {
+ this.$el.removeClass( "tool-node-error" );
+ }
+ },
+
+ newInputsDiv: function() {
+ return $("<div class='inputs'></div>");
+ },
+
+ updateMaxWidth: function( newWidth ) {
+ this.output_width = Math.max( this.output_width, newWidth );
+ },
+
+ addRule: function() {
+ this.tool_body.append( $( "<div class='rule'></div>" ) );
+ },
+
+ addDataInput: function( input ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var terminalElement = terminalView.el;
+ var inputView = new DataInputView( {
+ "terminalElement": terminalElement,
+ "input": input,
+ "nodeView": this,
+ } );
+ var ib = inputView.$el;
+ var terminalElement = inputView.terminalElement;
+ this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
+ },
+
+ replaceDataInput: function( input, new_body ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var t = terminalView.el;
+
+ // If already connected save old connection
+ this.$( "div[name='" + input.name + "']" ).each( function() {
+ $(this).find( ".input-terminal" ).each( function() {
+ var c = this.terminal.connectors[0];
+ if ( c ) {
+ t.terminal.connectors[0] = c;
+ c.handle2 = t.terminal;
+ }
+ });
+ $(this).remove();
+ });
+ var inputView = new DataInputView( {
+ "terminalElement": t,
+ "input": input,
+ "nodeView": this,
+ "skipResize": true,
+ } );
+ var ib = inputView.$el;
+
+ // Append to new body
+ new_body.append( ib.prepend( t ) );
+
+ },
+
+ addDataOutput: function( output ) {
+ var terminalView = new OutputTerminalView( {
+ node: this.node,
+ output: output
+ } );
+ var outputView = new DataOutputView( {
+ "output": output,
+ "terminalElement": terminalView.el,
+ "nodeView": this,
+ } );
+ this.tool_body.append( outputView.$el.append( outputView.terminalElement ) );
+ }
+
+} );
+
+
+
+var DataInputView = Backbone.View.extend( {
+ className: "form-row dataRow input-data-row",
+
+ initialize: function( options ){
+ this.input = options.input;
+ this.nodeView = options.nodeView;
+ this.terminalElement = options.terminalElement;
+
+ this.$el.attr( "name", this.input.name )
+ .html( this.input.label );
+
+ if( ! options.skipResize ) {
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+ $('body').append(this.el);
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' });
+ this.$el.remove();
+ }
+ },
+
+} );
+
+
+
+var OutputCalloutView = Backbone.View.extend( {
+ tagName: "div",
+
+ initialize: function( options ) {
+ this.label = options.label;
+ this.node = options.node;
+ this.output = options.output;
+
+ var view = this;
+ this.$el
+ .attr( "class", 'callout '+this.label )
+ .css( { display: 'none' } )
+ .append(
+ $("<div class='buttons'></div>").append(
+ $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
+ if ($.inArray(view.output.name, view.node.workflow_outputs) != -1){
+ view.node.workflow_outputs.splice($.inArray(view.output.name, view.node.workflow_outputs), 1);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ }else{
+ view.node.workflow_outputs.push(view.output.name);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ workflow.has_changes = true;
+ canvas_manager.draw_overview();
+ })))
+ .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
+
+ this.$el.css({
+ top: '50%',
+ margin:'-8px 0px 0px 0px',
+ right: 8
+ });
+ this.$el.show();
+ this.resetImage();
+ },
+
+ resetImage: function() {
+ if ($.inArray( this.output.name, this.node.workflow_outputs) === -1){
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ } else{
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ },
+
+ hoverImage: function() {
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
+ }
+
+} );
+
+
+
+
+var DataOutputView = Backbone.View.extend( {
+ className: "form-row dataRow",
+
+ initialize: function( options ) {
+ this.output = options.output;
+ this.terminalElement = options.terminalElement;
+ this.nodeView = options.nodeView;
+
+ var output = this.output;
+ var label = output.name;
+ var node = this.nodeView.node;
+ if ( output.extensions.indexOf( 'input' ) < 0 ) {
+ label = label + " (" + output.extensions.join(", ") + ")";
+ }
+ this.$el.html( label )
+
+ if (node.type == 'tool'){
+ var calloutView = new OutputCalloutView( {
+ "label": label,
+ "output": output,
+ "node": node,
+ });
+ this.$el.append( calloutView.el );
+ this.$el.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
+ }
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+ $('body').append( this.el );
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() + 17 );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' })
+ .detach();
+ }
+
+} );
+
+
+
+var InputTerminalView = Backbone.View.extend( {
+ className: "terminal input-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var input = options.input;
+
+ var name = input.name;
+ var types = input.extensions;
+ var multiple = input.multiple;
+
+ var terminal = this.el.terminal = new InputTerminal( { element: this.el, datatypes: types, multiple: multiple } );
+ terminal.node = node;
+ terminal.name = name;
+
+ node.input_terminals[name] = terminal;
+ },
+
+ events: {
+ "dropinit": "onDropInit",
+ "dropstart": "onDropStart",
+ "dropend": "onDropEnd",
+ "drop": "onDrop",
+ "hover": "onHover",
+ },
+
+ onDropInit: function( e, d ) {
+ var terminal = this.el.terminal;
+ // Accept a dragable if it is an output terminal and has a
+ // compatible type
+ return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
+ },
+
+ onDropStart: function( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
+ }
+ },
+
+ onDropEnd: function ( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
+ }
+ },
+
+ onDrop: function( e, d ) {
+ var terminal = this.el.terminal;
+ new Connector( d.drag.terminal, terminal ).redraw();
+ },
+
+ onHover: function() {
+ var element = this.el;
+ var terminal = element.terminal;
+
+ // If connected, create a popup to allow disconnection
+ if ( terminal.connectors.length > 0 ) {
+ // Create callout
+ var t = $("<div class='callout'></div>")
+ .css( { display: 'none' } )
+ .appendTo( "body" )
+ .append(
+ $("<div class='button'></div>").append(
+ $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
+ $.each( terminal.connectors, function( _, x ) {
+ if (x) {
+ x.destroy();
+ }
+ });
+ t.remove();
+ })))
+ .bind( "mouseleave", function() {
+ $(this).remove();
+ });
+ // Position it and show
+ t.css({
+ top: $(element).offset().top - 2,
+ left: $(element).offset().left - t.width(),
+ 'padding-right': $(element).width()
+ }).show();
+ }
+ },
+
+} );
+
+
+
+var OutputTerminalView = Backbone.View.extend( {
+ className: "terminal output-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var output = options.output;
+ var name = output.name;
+ var type = output.extensions;
+
+ var element = this.el;
+ var terminal_element = element;
+ var terminal = element.terminal = new OutputTerminal( {element: element, datatypes: type } );
+ terminal.node = node;
+ terminal.name = name;
+ node.output_terminals[name] = terminal;
+ },
+
+ events: {
+ "drag": "onDrag",
+ "dragstart": "onDragStart",
+ "dragend": "onDragEnd",
+ },
+
+ onDrag: function ( e, d ) {
+ var onmove = function() {
+ var po = $(d.proxy).offsetParent().offset(),
+ x = d.offsetX - po.left,
+ y = d.offsetY - po.top;
+ $(d.proxy).css( { left: x, top: y } );
+ d.proxy.terminal.redraw();
+ // FIXME: global
+ canvas_manager.update_viewport_overlay();
+ };
+ onmove();
+ $("#canvas-container").get(0).scroll_panel.test( e, onmove );
+ },
+
+ onDragStart: function( e, d ) {
+ $( d.available ).addClass( "input-terminal-active" );
+ // Save PJAs in the case of change datatype actions.
+ workflow.check_changes_in_active_form();
+ // Drag proxy div
+ var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
+ .appendTo( "#canvas-container" ).get(0);
+ // Terminal and connection to display noodle while dragging
+ h.terminal = new OutputTerminal( { element: h } );
+ var c = new Connector();
+ c.dragging = true;
+ c.connect( this.el.terminal, h.terminal );
+ return h;
+ },
+
+ onDragEnd: function ( e, d ) {
+ d.proxy.terminal.connectors[0].destroy();
+ $(d.proxy).remove();
+ $( d.available ).removeClass( "input-terminal-active" );
+ $("#canvas-container").get(0).scroll_panel.stop();
+ }
+
+} );
+
+
+
+////////////
+// END VIEWS
+////////////
+
+
// FIXME: merge scroll panel into CanvasManager, clean up hardcoded stuff.
function ScrollPanel( panel ) {
https://bitbucket.org/galaxy/galaxy-central/commits/991f6ba12df4/
Changeset: 991f6ba12df4
User: jmchilton
Date: 2014-04-19 18:57:53
Summary: Merge pull request #363.
Was previously declined so that pull request #370 could be resolved first - but upon actually inspecting #370 I don't think these will conflict in anyway.
Affected #: 2 files
diff -r 439510f01e3b0850fd844cded14977076ec86501 -r 991f6ba12df4dddcded9a813bd5e55e70ad31841 static/scripts/galaxy.workflow_editor.canvas.js
--- a/static/scripts/galaxy.workflow_editor.canvas.js
+++ b/static/scripts/galaxy.workflow_editor.canvas.js
@@ -1,18 +1,18 @@
-function Terminal( element ) {
- this.element = element;
- this.connectors = [];
-}
-$.extend( Terminal.prototype, {
+var Terminal = Backbone.Model.extend( {
+ initialize: function( attr ) {
+ this.element = attr.element;
+ this.connectors = [];
+ },
connect: function ( connector ) {
this.connectors.push( connector );
if ( this.node ) {
- this.node.changed();
+ this.node.markChanged();
}
},
disconnect: function ( connector ) {
this.connectors.splice( $.inArray( connector, this.connectors ), 1 );
if ( this.node ) {
- this.node.changed();
+ this.node.markChanged();
}
},
redraw: function () {
@@ -25,24 +25,22 @@
c.destroy();
});
}
-});
+} );
-function OutputTerminal( element, datatypes ) {
- Terminal.call( this, element );
- this.datatypes = datatypes;
-}
+var OutputTerminal = Terminal.extend( {
+ initialize: function( attr ) {
+ Terminal.prototype.initialize.call( this, attr );
+ this.datatypes = attr.datatypes;
+ }
+} );
-OutputTerminal.prototype = new Terminal();
-function InputTerminal( element, datatypes, multiple ) {
- Terminal.call( this, element );
- this.datatypes = datatypes;
- this.multiple = multiple
-}
-
-InputTerminal.prototype = new Terminal();
-
-$.extend( InputTerminal.prototype, {
+var InputTerminal = Terminal.extend( {
+ initialize: function( attr ) {
+ Terminal.prototype.initialize.call( this, attr );
+ this.datatypes = attr.datatypes;
+ this.multiple = attr.multiple;
+ },
can_accept: function ( other ) {
if ( this.connectors.length < 1 || this.multiple) {
for ( var t in this.datatypes ) {
@@ -68,6 +66,8 @@
}
});
+
+
function Connector( handle1, handle2 ) {
this.canvas = null;
this.dragging = false;
@@ -164,106 +164,13 @@
}
} );
-function Node( element ) {
- this.element = element;
- this.input_terminals = {};
- this.output_terminals = {};
- this.tool_errors = {};
-}
-$.extend( Node.prototype, {
- new_input_terminal : function( input ) {
- var t = $("<div class='terminal input-terminal'></div>")[ 0 ];
- this.enable_input_terminal( t, input.name, input.extensions, input.multiple );
- return t;
- },
- enable_input_terminal : function( element, name, types, multiple ) {
- var node = this;
+var Node = Backbone.Model.extend({
- var terminal = element.terminal = new InputTerminal( element, types, multiple );
- terminal.node = node;
- terminal.name = name;
- $(element).bind( "dropinit", function( e, d ) {
- // Accept a dragable if it is an output terminal and has a
- // compatible type
- return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
- }).bind( "dropstart", function( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
- }
- }).bind( "dropend", function ( e, d ) {
- if (d.proxy.terminal) {
- d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
- }
- }).bind( "drop", function( e, d ) {
- ( new Connector( d.drag.terminal, terminal ) ).redraw();
- }).bind( "hover", function() {
- // If connected, create a popup to allow disconnection
- if ( terminal.connectors.length > 0 ) {
- // Create callout
- var t = $("<div class='callout'></div>")
- .css( { display: 'none' } )
- .appendTo( "body" )
- .append(
- $("<div class='button'></div>").append(
- $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
- $.each( terminal.connectors, function( _, x ) {
- if (x) {
- x.destroy();
- }
- });
- t.remove();
- })))
- .bind( "mouseleave", function() {
- $(this).remove();
- });
- // Position it and show
- t.css({
- top: $(element).offset().top - 2,
- left: $(element).offset().left - t.width(),
- 'padding-right': $(element).width()
- }).show();
- }
- });
- node.input_terminals[name] = terminal;
- },
- enable_output_terminal : function( element, name, type ) {
- var node = this;
- var terminal_element = element;
- var terminal = element.terminal = new OutputTerminal( element, type );
- terminal.node = node;
- terminal.name = name;
- $(element).bind( "dragstart", function( e, d ) {
- $( d.available ).addClass( "input-terminal-active" );
- // Save PJAs in the case of change datatype actions.
- workflow.check_changes_in_active_form();
- // Drag proxy div
- var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
- .appendTo( "#canvas-container" ).get(0);
- // Terminal and connection to display noodle while dragging
- h.terminal = new OutputTerminal( h );
- var c = new Connector();
- c.dragging = true;
- c.connect( element.terminal, h.terminal );
- return h;
- }).bind( "drag", function ( e, d ) {
- var onmove = function() {
- var po = $(d.proxy).offsetParent().offset(),
- x = d.offsetX - po.left,
- y = d.offsetY - po.top;
- $(d.proxy).css( { left: x, top: y } );
- d.proxy.terminal.redraw();
- // FIXME: global
- canvas_manager.update_viewport_overlay();
- };
- onmove();
- $("#canvas-container").get(0).scroll_panel.test( e, onmove );
- }).bind( "dragend", function ( e, d ) {
- d.proxy.terminal.connectors[0].destroy();
- $(d.proxy).remove();
- $( d.available ).removeClass( "input-terminal-active" );
- $("#canvas-container").get(0).scroll_panel.stop();
- });
- node.output_terminals[name] = terminal;
+ initialize: function( attr ) {
+ this.element = attr.element;
+ this.input_terminals = {};
+ this.output_terminals = {};
+ this.tool_errors = {};
},
redraw : function () {
$.each( this.input_terminals, function( _, t ) {
@@ -295,7 +202,6 @@
$(element).removeClass( "toolForm-active" );
},
init_field_data : function ( data ) {
- var f = this.element;
if ( data.type ) {
this.type = data.type;
}
@@ -308,132 +214,40 @@
this.post_job_actions = data.post_job_actions ? data.post_job_actions : {};
this.workflow_outputs = data.workflow_outputs ? data.workflow_outputs : [];
- if ( this.tool_errors ) {
- f.addClass( "tool-node-error" );
- } else {
- f.removeClass( "tool-node-error" );
- }
var node = this;
- var output_width = Math.max(150, f.width());
- var b = f.find( ".toolFormBody" );
- b.find( "div" ).remove();
- var ibox = $("<div class='inputs'></div>").appendTo( b );
+ var nodeView = new NodeView({
+ el: this.element[ 0 ],
+ node: node,
+ });
+ node.nodeView = nodeView;
+
$.each( data.data_inputs, function( i, input ) {
- var t = node.new_input_terminal( input );
- var ib = $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" );
- ib.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append(ib);
- output_width = Math.max(output_width, ib.outerWidth());
- ib.css({ position:'',
- left:'',
- top:'',
- display:'' });
- ib.remove();
- ibox.append( ib.prepend( t ) );
+ nodeView.addDataInput( input );
});
if ( ( data.data_inputs.length > 0 ) && ( data.data_outputs.length > 0 ) ) {
- b.append( $( "<div class='rule'></div>" ) );
+ nodeView.addRule();
}
$.each( data.data_outputs, function( i, output ) {
- var t = $( "<div class='terminal output-terminal'></div>" );
- node.enable_output_terminal( t[ 0 ], output.name, output.extensions );
- var label = output.name;
- if ( output.extensions.indexOf( 'input' ) < 0 ) {
- label = label + " (" + output.extensions.join(", ") + ")";
- }
- var r = $("<div class='form-row dataRow'>" + label + "</div>" );
- if (node.type == 'tool'){
- var callout = $("<div class='callout "+label+"'></div>")
- .css( { display: 'none' } )
- .append(
- $("<div class='buttons'></div>").append(
- $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
- if ($.inArray(output.name, node.workflow_outputs) != -1){
- node.workflow_outputs.splice($.inArray(output.name, node.workflow_outputs), 1);
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- node.workflow_outputs.push(output.name);
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- workflow.has_changes = true;
- canvas_manager.draw_overview();
- })))
- .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
- callout.css({
- top: '50%',
- margin:'-8px 0px 0px 0px',
- right: 8
- });
- callout.show();
- r.append(callout);
- if ($.inArray(output.name, node.workflow_outputs) === -1){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- r.hover(
- function(){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
- },
- function(){
- if ($.inArray(output.name, node.workflow_outputs) === -1){
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
- }else{
- callout.find('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
- }
- });
- }
- r.css({ position:'absolute',
- left: -1000,
- top: -1000,
- display:'none'});
- $('body').append(r);
- output_width = Math.max(output_width, r.outerWidth() + 17);
- r.css({ position:'',
- left:'',
- top:'',
- display:'' });
- r.detach();
- b.append( r.append( t ) );
- });
- f.css( "width", Math.min(250, Math.max(f.width(), output_width )));
+ nodeView.addDataOutput( output );
+ } );
+ nodeView.render();
workflow.node_changed( this );
},
update_field_data : function( data ) {
- var el = $(this.element),
- node = this;
+ var node = this;
+ nodeView = node.nodeView;
this.tool_state = data.tool_state;
this.form_html = data.form_html;
this.tool_errors = data.tool_errors;
this.annotation = data['annotation'];
var pja_in = $.parseJSON(data.post_job_actions);
this.post_job_actions = pja_in ? pja_in : {};
- if ( this.tool_errors ) {
- el.addClass( "tool-node-error" );
- } else {
- el.removeClass( "tool-node-error" );
- }
+ node.nodeView.renderToolErrors();
// Update input rows
- var old_body = el.find( "div.inputs" );
- var new_body = $("<div class='inputs'></div>");
+ var old_body = nodeView.$( "div.inputs" );
+ var new_body = nodeView.newInputsDiv();
$.each( data.data_inputs, function( i, input ) {
- var t = node.new_input_terminal( input );
- // If already connected save old connection
- old_body.find( "div[name='" + input.name + "']" ).each( function() {
- $(this).find( ".input-terminal" ).each( function() {
- var c = this.terminal.connectors[0];
- if ( c ) {
- t.terminal.connectors[0] = c;
- c.handle2 = t.terminal;
- }
- });
- $(this).remove();
- });
- // Append to new body
- new_body.append( $("<div class='form-row dataRow input-data-row' name='" + input.name + "'>" + input.label + "</div>" ).prepend( t ) );
+ node.nodeView.replaceDataInput( input, new_body );
});
old_body.replaceWith( new_body );
// Cleanup any leftover terminals
@@ -441,7 +255,7 @@
this.terminal.destroy();
});
// If active, reactivate with new form_html
- this.changed();
+ this.markChanged();
this.redraw();
},
error : function ( text ) {
@@ -452,7 +266,7 @@
b.html( tmp );
workflow.node_changed( this );
},
- changed: function() {
+ markChanged: function() {
workflow.node_changed( this );
}
} );
@@ -837,7 +651,7 @@
function prebuild_node( type, title_text, tool_id ) {
var f = $("<div class='toolForm toolFormInCanvas'></div>");
- var node = new Node( f );
+ var node = new Node( { element: f } );
node.type = type;
if ( type == 'tool' ) {
node.tool_id = tool_id;
@@ -916,6 +730,389 @@
type_to_type = data.class_to_classes;
}
+
+//////////////
+// START VIEWS
+//////////////
+
+
+var NodeView = Backbone.View.extend( {
+ initialize: function( options ){
+ this.node = options.node;
+ this.output_width = Math.max(150, this.$el.width());
+ this.tool_body = this.$el.find( ".toolFormBody" );
+ this.tool_body.find( "div" ).remove();
+ this.newInputsDiv().appendTo( this.tool_body );
+ },
+
+ render : function() {
+ this.renderToolErrors();
+ this.$el.css( "width", Math.min(250, Math.max(this.$el.width(), this.output_width )));
+ },
+
+ renderToolErrors: function( ) {
+ if ( this.node.tool_errors ) {
+ this.$el.addClass( "tool-node-error" );
+ } else {
+ this.$el.removeClass( "tool-node-error" );
+ }
+ },
+
+ newInputsDiv: function() {
+ return $("<div class='inputs'></div>");
+ },
+
+ updateMaxWidth: function( newWidth ) {
+ this.output_width = Math.max( this.output_width, newWidth );
+ },
+
+ addRule: function() {
+ this.tool_body.append( $( "<div class='rule'></div>" ) );
+ },
+
+ addDataInput: function( input ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var terminalElement = terminalView.el;
+ var inputView = new DataInputView( {
+ "terminalElement": terminalElement,
+ "input": input,
+ "nodeView": this,
+ } );
+ var ib = inputView.$el;
+ var terminalElement = inputView.terminalElement;
+ this.$( ".inputs" ).append( ib.prepend( terminalElement ) );
+ },
+
+ replaceDataInput: function( input, new_body ) {
+ var terminalView = new InputTerminalView( {
+ node: this.node,
+ input: input
+ } );
+ var t = terminalView.el;
+
+ // If already connected save old connection
+ this.$( "div[name='" + input.name + "']" ).each( function() {
+ $(this).find( ".input-terminal" ).each( function() {
+ var c = this.terminal.connectors[0];
+ if ( c ) {
+ t.terminal.connectors[0] = c;
+ c.handle2 = t.terminal;
+ }
+ });
+ $(this).remove();
+ });
+ var inputView = new DataInputView( {
+ "terminalElement": t,
+ "input": input,
+ "nodeView": this,
+ "skipResize": true,
+ } );
+ var ib = inputView.$el;
+
+ // Append to new body
+ new_body.append( ib.prepend( t ) );
+
+ },
+
+ addDataOutput: function( output ) {
+ var terminalView = new OutputTerminalView( {
+ node: this.node,
+ output: output
+ } );
+ var outputView = new DataOutputView( {
+ "output": output,
+ "terminalElement": terminalView.el,
+ "nodeView": this,
+ } );
+ this.tool_body.append( outputView.$el.append( outputView.terminalElement ) );
+ }
+
+} );
+
+
+
+var DataInputView = Backbone.View.extend( {
+ className: "form-row dataRow input-data-row",
+
+ initialize: function( options ){
+ this.input = options.input;
+ this.nodeView = options.nodeView;
+ this.terminalElement = options.terminalElement;
+
+ this.$el.attr( "name", this.input.name )
+ .html( this.input.label );
+
+ if( ! options.skipResize ) {
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+ $('body').append(this.el);
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' });
+ this.$el.remove();
+ }
+ },
+
+} );
+
+
+
+var OutputCalloutView = Backbone.View.extend( {
+ tagName: "div",
+
+ initialize: function( options ) {
+ this.label = options.label;
+ this.node = options.node;
+ this.output = options.output;
+
+ var view = this;
+ this.$el
+ .attr( "class", 'callout '+this.label )
+ .css( { display: 'none' } )
+ .append(
+ $("<div class='buttons'></div>").append(
+ $("<img/>").attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png').click( function() {
+ if ($.inArray(view.output.name, view.node.workflow_outputs) != -1){
+ view.node.workflow_outputs.splice($.inArray(view.output.name, view.node.workflow_outputs), 1);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ }else{
+ view.node.workflow_outputs.push(view.output.name);
+ view.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ workflow.has_changes = true;
+ canvas_manager.draw_overview();
+ })))
+ .tooltip({delay:500, title: "Mark dataset as a workflow output. All unmarked datasets will be hidden." });
+
+ this.$el.css({
+ top: '50%',
+ margin:'-8px 0px 0px 0px',
+ right: 8
+ });
+ this.$el.show();
+ this.resetImage();
+ },
+
+ resetImage: function() {
+ if ($.inArray( this.output.name, this.node.workflow_outputs) === -1){
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-outline.png');
+ } else{
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small.png');
+ }
+ },
+
+ hoverImage: function() {
+ this.$('img').attr('src', galaxy_config.root + 'static/images/fugue/asterisk-small-yellow.png');
+ }
+
+} );
+
+
+
+
+var DataOutputView = Backbone.View.extend( {
+ className: "form-row dataRow",
+
+ initialize: function( options ) {
+ this.output = options.output;
+ this.terminalElement = options.terminalElement;
+ this.nodeView = options.nodeView;
+
+ var output = this.output;
+ var label = output.name;
+ var node = this.nodeView.node;
+ if ( output.extensions.indexOf( 'input' ) < 0 ) {
+ label = label + " (" + output.extensions.join(", ") + ")";
+ }
+ this.$el.html( label )
+
+ if (node.type == 'tool'){
+ var calloutView = new OutputCalloutView( {
+ "label": label,
+ "output": output,
+ "node": node,
+ });
+ this.$el.append( calloutView.el );
+ this.$el.hover( function() { calloutView.hoverImage() }, function() { calloutView.resetImage() } );
+ }
+ this.$el.css({ position:'absolute',
+ left: -1000,
+ top: -1000,
+ display:'none'});
+ $('body').append( this.el );
+ this.nodeView.updateMaxWidth( this.$el.outerWidth() + 17 );
+ this.$el.css({ position:'',
+ left:'',
+ top:'',
+ display:'' })
+ .detach();
+ }
+
+} );
+
+
+
+var InputTerminalView = Backbone.View.extend( {
+ className: "terminal input-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var input = options.input;
+
+ var name = input.name;
+ var types = input.extensions;
+ var multiple = input.multiple;
+
+ var terminal = this.el.terminal = new InputTerminal( { element: this.el, datatypes: types, multiple: multiple } );
+ terminal.node = node;
+ terminal.name = name;
+
+ node.input_terminals[name] = terminal;
+ },
+
+ events: {
+ "dropinit": "onDropInit",
+ "dropstart": "onDropStart",
+ "dropend": "onDropEnd",
+ "drop": "onDrop",
+ "hover": "onHover",
+ },
+
+ onDropInit: function( e, d ) {
+ var terminal = this.el.terminal;
+ // Accept a dragable if it is an output terminal and has a
+ // compatible type
+ return $(d.drag).hasClass( "output-terminal" ) && terminal.can_accept( d.drag.terminal );
+ },
+
+ onDropStart: function( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#BBFFBB";
+ }
+ },
+
+ onDropEnd: function ( e, d ) {
+ if (d.proxy.terminal) {
+ d.proxy.terminal.connectors[0].inner_color = "#FFFFFF";
+ }
+ },
+
+ onDrop: function( e, d ) {
+ var terminal = this.el.terminal;
+ new Connector( d.drag.terminal, terminal ).redraw();
+ },
+
+ onHover: function() {
+ var element = this.el;
+ var terminal = element.terminal;
+
+ // If connected, create a popup to allow disconnection
+ if ( terminal.connectors.length > 0 ) {
+ // Create callout
+ var t = $("<div class='callout'></div>")
+ .css( { display: 'none' } )
+ .appendTo( "body" )
+ .append(
+ $("<div class='button'></div>").append(
+ $("<div/>").addClass("fa-icon-button fa fa-times").click( function() {
+ $.each( terminal.connectors, function( _, x ) {
+ if (x) {
+ x.destroy();
+ }
+ });
+ t.remove();
+ })))
+ .bind( "mouseleave", function() {
+ $(this).remove();
+ });
+ // Position it and show
+ t.css({
+ top: $(element).offset().top - 2,
+ left: $(element).offset().left - t.width(),
+ 'padding-right': $(element).width()
+ }).show();
+ }
+ },
+
+} );
+
+
+
+var OutputTerminalView = Backbone.View.extend( {
+ className: "terminal output-terminal",
+
+ initialize: function( options ) {
+ var node = options.node;
+ var output = options.output;
+ var name = output.name;
+ var type = output.extensions;
+
+ var element = this.el;
+ var terminal_element = element;
+ var terminal = element.terminal = new OutputTerminal( {element: element, datatypes: type } );
+ terminal.node = node;
+ terminal.name = name;
+ node.output_terminals[name] = terminal;
+ },
+
+ events: {
+ "drag": "onDrag",
+ "dragstart": "onDragStart",
+ "dragend": "onDragEnd",
+ },
+
+ onDrag: function ( e, d ) {
+ var onmove = function() {
+ var po = $(d.proxy).offsetParent().offset(),
+ x = d.offsetX - po.left,
+ y = d.offsetY - po.top;
+ $(d.proxy).css( { left: x, top: y } );
+ d.proxy.terminal.redraw();
+ // FIXME: global
+ canvas_manager.update_viewport_overlay();
+ };
+ onmove();
+ $("#canvas-container").get(0).scroll_panel.test( e, onmove );
+ },
+
+ onDragStart: function( e, d ) {
+ $( d.available ).addClass( "input-terminal-active" );
+ // Save PJAs in the case of change datatype actions.
+ workflow.check_changes_in_active_form();
+ // Drag proxy div
+ var h = $( '<div class="drag-terminal" style="position: absolute;"></div>' )
+ .appendTo( "#canvas-container" ).get(0);
+ // Terminal and connection to display noodle while dragging
+ h.terminal = new OutputTerminal( { element: h } );
+ var c = new Connector();
+ c.dragging = true;
+ c.connect( this.el.terminal, h.terminal );
+ return h;
+ },
+
+ onDragEnd: function ( e, d ) {
+ d.proxy.terminal.connectors[0].destroy();
+ $(d.proxy).remove();
+ $( d.available ).removeClass( "input-terminal-active" );
+ $("#canvas-container").get(0).scroll_panel.stop();
+ }
+
+} );
+
+
+
+////////////
+// END VIEWS
+////////////
+
+
// FIXME: merge scroll panel into CanvasManager, clean up hardcoded stuff.
function ScrollPanel( panel ) {
diff -r 439510f01e3b0850fd844cded14977076ec86501 -r 991f6ba12df4dddcded9a813bd5e55e70ad31841 test/qunit/tests/workflow_editor_tests.js
--- a/test/qunit/tests/workflow_editor_tests.js
+++ b/test/qunit/tests/workflow_editor_tests.js
@@ -58,7 +58,7 @@
setup: function() {
this.node = { };
this.element = $( "<div>" );
- this.input_terminal = new InputTerminal( this.element, [ "txt" ] );
+ this.input_terminal = new InputTerminal( { element: this.element, datatypes: [ "txt" ] } );
this.input_terminal.node = this.node;
},
test_connector: function( attr ) {
@@ -81,25 +81,25 @@
} );
test( "test connect", function() {
- this.node.changed = sinon.spy();
+ this.node.markChanged = sinon.spy();
var connector = {};
this.input_terminal.connect( connector );
- // Assert node changed called
- ok( this.node.changed.called );
+ // Assert node markChanged called
+ ok( this.node.markChanged.called );
// Assert connectors updated
ok( this.input_terminal.connectors[ 0 ] === connector );
} );
test( "test disconnect", function() {
- this.node.changed = sinon.spy();
+ this.node.markChanged = sinon.spy();
var connector = this.test_connector( {} );
this.input_terminal.disconnect( connector );
- // Assert node changed called
- ok( this.node.changed.called );
+ // Assert node markChanged called
+ ok( this.node.markChanged.called );
// Assert connectors updated
equal( this.input_terminal.connectors.length, 0 );
} );
@@ -204,7 +204,7 @@
this.input_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.output_terminal = { destroy: sinon.spy(), redraw: sinon.spy() };
this.element = $("<div><div class='toolFormBody'></div></div>");
- this.node = new Node( this.element );
+ this.node = new Node( { element: this.element } );
this.node.input_terminals.i1 = this.input_terminal;
this.node.output_terminals.o1 = this.output_terminal;
},
@@ -376,4 +376,92 @@
} );
} );
+ /* global NodeView */
+ module( "Node view ", {
+ setup: function() {
+ this.set_for_node( {} );
+ },
+ set_for_node: function( node ) {
+ var element = $("<div>");
+ this.view = new NodeView( { node: node, el: element[ 0 ] } );
+ },
+ } );
+
+ test( "tool error styling", function() {
+ this.set_for_node( { tool_errors: false } );
+ this.view.render();
+ ok( ! this.view.$el.hasClass( "tool-node-error" ) );
+ this.set_for_node( { tool_errors: true } );
+ this.view.render();
+ ok( this.view.$el.hasClass( "tool-node-error" ) );
+ } );
+
+ test( "rendering correct width", function() {
+ // Default width is 150
+ this.view.render();
+ equal( this.view.$el.width(), 150 );
+
+ // If any data rows are greater, it will update
+ this.view.updateMaxWidth( 200 );
+ this.view.render();
+ equal( this.view.$el.width(), 200 );
+
+ // However 250 is the maximum width of node
+ this.view.updateMaxWidth( 300 );
+ this.view.render();
+ equal( this.view.$el.width(), 250 );
+
+ } );
+
+ /* global InputTerminalView */
+ module( "Input terminal view", {
+ setup: function() {
+ this.node = { input_terminals: [] };
+ this.input = { name: "i1", extensions: "txt", multiple: false };
+ this.view = new InputTerminalView( {
+ node: this.node,
+ input: this.input,
+ });
+ }
+ } );
+
+ test( "terminal added to node", function() {
+ ok( this.node.input_terminals.i1 );
+ equal( this.node.input_terminals.i1.datatypes, [ "txt" ] );
+ equal( this.node.input_terminals.i1.multiple, false );
+ } );
+
+ test( "terminal element", function() {
+ var el = this.view.el;
+ equal( el.tagName, "DIV" );
+ equal( el.className, "terminal input-terminal");
+ } );
+
+ // TODO: Test binding... not sure how to do that exactly..
+
+ /* global OutputTerminalView */
+ module( "Output terminal view", {
+ setup: function() {
+ this.node = { output_terminals: [] };
+ this.output = { name: "o1", extensions: "txt" };
+ this.view = new OutputTerminalView( {
+ node: this.node,
+ output: this.output,
+ });
+ }
+ } );
+
+ test( "terminal added to node", function() {
+ ok( this.node.output_terminals.o1 );
+ equal( this.node.output_terminals.o1.datatypes, [ "txt" ] );
+ } );
+
+ test( "terminal element", function() {
+ var el = this.view.el;
+ equal( el.tagName, "DIV" );
+ equal( el.className, "terminal output-terminal");
+ } );
+
+ // TODO: Test bindings
+
});
\ 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
2 new commits in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4a7abc7892db/
Changeset: 4a7abc7892db
User: jmchilton
Date: 2014-04-19 18:40:19
Summary: Refactor galaxy.workflow.run interface to use config object.
Number of ways to paramemterize workflow is a little bit sprawling already and it is about to get worse.
Affected #: 3 files
diff -r 4b430f408ac762a6f2a6856fb199a347bc693fbb -r 4a7abc7892db4d6c9046b1ad46e8b04925b052e3 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -14,6 +14,7 @@
from galaxy.web.base.controller import UsesHistoryMixin
from galaxy.workflow.modules import module_factory
from galaxy.workflow.run import invoke
+from galaxy.workflow.run import WorkflowRunConfig
from galaxy.workflow.extract import extract_workflow
@@ -325,12 +326,17 @@
# Run each step, connecting outputs to inputs
replacement_dict = payload.get('replacement_params', {})
+
+ run_config = WorkflowRunConfig(
+ target_history=history,
+ replacement_dict=replacement_dict,
+ ds_map=ds_map,
+ )
+
outputs = invoke(
trans=trans,
workflow=workflow,
- target_history=history,
- replacement_dict=replacement_dict,
- ds_map=ds_map,
+ workflow_run_config=run_config,
)
trans.sa_session.flush()
diff -r 4b430f408ac762a6f2a6856fb199a347bc693fbb -r 4a7abc7892db4d6c9046b1ad46e8b04925b052e3 lib/galaxy/webapps/galaxy/controllers/workflow.py
--- a/lib/galaxy/webapps/galaxy/controllers/workflow.py
+++ b/lib/galaxy/webapps/galaxy/controllers/workflow.py
@@ -29,6 +29,7 @@
from galaxy.web.framework.helpers import to_unicode
from galaxy.workflow.modules import module_factory
from galaxy.workflow.run import invoke
+from galaxy.workflow.run import WorkflowRunConfig
from galaxy.workflow.extract import summarize
from galaxy.workflow.extract import extract_workflow
from galaxy.workflow.steps import (
@@ -1322,12 +1323,16 @@
if k.startswith('wf_parm|'):
replacement_dict[k[8:]] = v
+ run_config = WorkflowRunConfig(
+ target_history=target_history,
+ replacement_dict=replacement_dict,
+ copy_inputs_to_history=new_history is not None
+ )
+
outputs = invoke(
trans=trans,
workflow=workflow,
- target_history=target_history,
- replacement_dict=replacement_dict,
- copy_inputs_to_history=new_history is not None
+ workflow_run_config=run_config
)
invocations.append({'outputs': outputs,
diff -r 4b430f408ac762a6f2a6856fb199a347bc693fbb -r 4a7abc7892db4d6c9046b1ad46e8b04925b052e3 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -8,28 +8,50 @@
from galaxy.util.odict import odict
-def invoke( trans, workflow, target_history, replacement_dict, copy_inputs_to_history=False, ds_map={} ):
+class WorkflowRunConfig( object ):
+ """ Wrapper around all the ways a workflow execution can be parameterized.
+
+ :param target_history: History to execute workflow in.
+ :type target_history: galaxy.model.History.
+
+ :param replacement_dict: Workflow level parameters used for renaming post
+ job actions.
+ :type replacement_dict: dict
+
+ :param copy_inputs_to_history: Should input data parameters be copied to
+ target_history. (Defaults to False)
+ :type copy_inputs_to_history: bool
+
+ :param ds_map: Map from step ids to dict's containing HDA for these steps.
+ :type ds_map: dict
+ """
+
+ def __init__( self, target_history, replacement_dict, copy_inputs_to_history=False, ds_map={} ):
+ self.target_history = target_history
+ self.replacement_dict = replacement_dict
+ self.copy_inputs_to_history = copy_inputs_to_history
+ self.ds_map = ds_map
+
+
+def invoke( trans, workflow, workflow_run_config ):
""" Run the supplied workflow in the supplied target_history.
"""
return WorkflowInvoker(
trans,
workflow,
- target_history,
- replacement_dict,
- copy_inputs_to_history=copy_inputs_to_history,
- ds_map=ds_map,
+ workflow_run_config,
).invoke()
class WorkflowInvoker( object ):
- def __init__( self, trans, workflow, target_history, replacement_dict, copy_inputs_to_history, ds_map ):
+ def __init__( self, trans, workflow, workflow_run_config ):
self.trans = trans
self.workflow = workflow
- self.target_history = target_history
- self.replacement_dict = replacement_dict
- self.copy_inputs_to_history = copy_inputs_to_history
- self.ds_map = ds_map
+ self.target_history = workflow_run_config.target_history
+ self.replacement_dict = workflow_run_config.replacement_dict
+ self.copy_inputs_to_history = workflow_run_config.copy_inputs_to_history
+ self.ds_map = workflow_run_config.ds_map
self.outputs = odict()
@@ -128,4 +150,4 @@
replacement = outputs[ connection[ 0 ].output_step.id ][ connection[ 0 ].output_name ]
return replacement
-__all__ = [ invoke ]
+__all__ = [ invoke, WorkflowRunConfig ]
https://bitbucket.org/galaxy/galaxy-central/commits/439510f01e3b/
Changeset: 439510f01e3b
User: jmchilton
Date: 2014-04-19 18:40:19
Summary: Refactor workflow API logic related to module population into run module.
Also moves runtime parameter override logic into that module as well. This is a good refactoring because it thins out a fat controllers (slightly) - but it is of particular interest because it makes it easier to recursively invoke potentially nested workflows from the workflow running module itself. It is still an open question whether that is desirable - see discussion on Pull Request #370 - but if it proves to be this can help enable it.
Affected #: 2 files
diff -r 4a7abc7892db4d6c9046b1ad46e8b04925b052e3 -r 439510f01e3b0850fd844cded14977076ec86501 lib/galaxy/webapps/galaxy/api/workflows.py
--- a/lib/galaxy/webapps/galaxy/api/workflows.py
+++ b/lib/galaxy/webapps/galaxy/api/workflows.py
@@ -21,39 +21,6 @@
log = logging.getLogger(__name__)
-def _update_step_parameters(step, param_map):
- """
- Update ``step`` parameters based on the user-provided ``param_map`` dict.
-
- ``param_map`` should be structured as follows::
-
- PARAM_MAP = {STEP_ID: PARAM_DICT, ...}
- PARAM_DICT = {NAME: VALUE, ...}
-
- For backwards compatibility, the following (deprecated) format is
- also supported for ``param_map``::
-
- PARAM_MAP = {TOOL_ID: PARAM_DICT, ...}
-
- in which case PARAM_DICT affects all steps with the given tool id.
- If both by-tool-id and by-step-id specifications are used, the
- latter takes precedence.
-
- Finally (again, for backwards compatibility), PARAM_DICT can also
- be specified as::
-
- PARAM_DICT = {'param': NAME, 'value': VALUE}
-
- Note that this format allows only one parameter to be set per step.
- """
- param_dict = param_map.get(step.tool_id, {}).copy()
- param_dict.update(param_map.get(str(step.id), {}))
- if param_dict:
- if 'param' in param_dict and 'value' in param_dict:
- param_dict[param_dict['param']] = param_dict['value']
- step.state.inputs.update(param_dict)
-
-
class WorkflowsAPIController(BaseAPIController, UsesStoredWorkflowMixin, UsesHistoryMixin):
@web.expose_api
@@ -290,40 +257,6 @@
trans.response.status = 400
return "Invalid Dataset '%s' Specified" % ds_map[k]['id']
- # Build the state for each step
- for step in workflow.steps:
- step_errors = None
- input_connections_by_name = {}
- for conn in step.input_connections:
- input_name = conn.input_name
- if not input_name in input_connections_by_name:
- input_connections_by_name[input_name] = []
- input_connections_by_name[input_name].append(conn)
- step.input_connections_by_name = input_connections_by_name
-
- if step.type == 'tool' or step.type is None:
- step.module = module_factory.from_workflow_step( trans, step )
- # Check for missing parameters
- step.upgrade_messages = step.module.check_and_update_state()
- # Any connected input needs to have value DummyDataset (these
- # are not persisted so we need to do it every time)
- step.module.add_dummy_datasets( connections=step.input_connections )
- step.state = step.module.state
- _update_step_parameters(step, param_map)
- if step.tool_errors:
- trans.response.status = 400
- return "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
- if step.upgrade_messages:
- trans.response.status = 400
- return "Workflow cannot be run because of step upgrade messages: %s" % step.upgrade_messages
- else:
- # This is an input step. Make sure we have an available input.
- if step.type == 'data_input' and str(step.id) not in ds_map:
- trans.response.status = 400
- return "Workflow cannot be run because an expected input step '%s' has no input dataset." % step.id
- step.module = module_factory.from_workflow_step( trans, step )
- step.state = step.module.get_runtime_state()
-
# Run each step, connecting outputs to inputs
replacement_dict = payload.get('replacement_params', {})
@@ -331,6 +264,7 @@
target_history=history,
replacement_dict=replacement_dict,
ds_map=ds_map,
+ param_map=param_map,
)
outputs = invoke(
diff -r 4a7abc7892db4d6c9046b1ad46e8b04925b052e3 -r 439510f01e3b0850fd844cded14977076ec86501 lib/galaxy/workflow/run.py
--- a/lib/galaxy/workflow/run.py
+++ b/lib/galaxy/workflow/run.py
@@ -6,6 +6,7 @@
from galaxy.tools.parameters.basic import DataToolParameter
from galaxy.tools.parameters import visit_input_values
from galaxy.util.odict import odict
+from galaxy.workflow import modules
class WorkflowRunConfig( object ):
@@ -24,13 +25,18 @@
:param ds_map: Map from step ids to dict's containing HDA for these steps.
:type ds_map: dict
+
+ :param param_map: Override tool and/or step parameters (see documentation on
+ _update_step_parameters below).
+ :type param_map:
"""
- def __init__( self, target_history, replacement_dict, copy_inputs_to_history=False, ds_map={} ):
+ def __init__( self, target_history, replacement_dict, copy_inputs_to_history=False, ds_map={}, param_map={} ):
self.target_history = target_history
self.replacement_dict = replacement_dict
self.copy_inputs_to_history = copy_inputs_to_history
self.ds_map = ds_map
+ self.param_map = param_map
def invoke( trans, workflow, workflow_run_config ):
@@ -52,6 +58,7 @@
self.replacement_dict = workflow_run_config.replacement_dict
self.copy_inputs_to_history = workflow_run_config.copy_inputs_to_history
self.ds_map = workflow_run_config.ds_map
+ self.param_map = workflow_run_config.param_map
self.outputs = odict()
@@ -59,6 +66,13 @@
workflow_invocation = model.WorkflowInvocation()
workflow_invocation.workflow = self.workflow
+ # Web controller will populate stateful modules on each step before calling invoke
+ # but not API controller. More work should be done to further harmonize these methods
+ # going forward if possible - if possible moving more web controller logic here.
+ modules_populated = not self.workflow.steps or hasattr( self.workflow.steps[ 0 ], "module" )
+ if not modules_populated:
+ self._populate_modules( )
+
for step in self.workflow.steps:
job = None
job = self._invoke_step( step )
@@ -150,4 +164,74 @@
replacement = outputs[ connection[ 0 ].output_step.id ][ connection[ 0 ].output_name ]
return replacement
+ def _populate_modules( self ):
+ # Build the state for each step
+ for step in self.workflow.steps:
+ step_errors = None
+ input_connections_by_name = {}
+ for conn in step.input_connections:
+ input_name = conn.input_name
+ if not input_name in input_connections_by_name:
+ input_connections_by_name[input_name] = []
+ input_connections_by_name[input_name].append(conn)
+ step.input_connections_by_name = input_connections_by_name
+
+ if step.type == 'tool' or step.type is None:
+ step.module = modules.module_factory.from_workflow_step( self.trans, step )
+ # Check for missing parameters
+ step.upgrade_messages = step.module.check_and_update_state()
+ # Any connected input needs to have value DummyDataset (these
+ # are not persisted so we need to do it every time)
+ step.module.add_dummy_datasets( connections=step.input_connections )
+ step.state = step.module.state
+ _update_step_parameters( step, self.param_map )
+ if step.tool_errors:
+ message = "Workflow cannot be run because of validation errors in some steps: %s" % step_errors
+ raise exceptions.MessageException( message )
+ if step.upgrade_messages:
+ message = "Workflow cannot be run because of step upgrade messages: %s" % step.upgrade_messages
+ raise exceptions.MessageException( message )
+ else:
+ # This is an input step. Make sure we have an available input.
+ if step.type == 'data_input' and str( step.id ) not in self.ds_map:
+ message = "Workflow cannot be run because an expected input step '%s' has no input dataset." % step.id
+ raise exceptions.MessageException( message )
+
+ step.module = modules.module_factory.from_workflow_step( self.trans, step )
+ step.state = step.module.get_runtime_state()
+
+
+def _update_step_parameters(step, param_map):
+ """
+ Update ``step`` parameters based on the user-provided ``param_map`` dict.
+
+ ``param_map`` should be structured as follows::
+
+ PARAM_MAP = {STEP_ID: PARAM_DICT, ...}
+ PARAM_DICT = {NAME: VALUE, ...}
+
+ For backwards compatibility, the following (deprecated) format is
+ also supported for ``param_map``::
+
+ PARAM_MAP = {TOOL_ID: PARAM_DICT, ...}
+
+ in which case PARAM_DICT affects all steps with the given tool id.
+ If both by-tool-id and by-step-id specifications are used, the
+ latter takes precedence.
+
+ Finally (again, for backwards compatibility), PARAM_DICT can also
+ be specified as::
+
+ PARAM_DICT = {'param': NAME, 'value': VALUE}
+
+ Note that this format allows only one parameter to be set per step.
+ """
+ param_dict = param_map.get(step.tool_id, {}).copy()
+ param_dict.update(param_map.get(str(step.id), {}))
+ if param_dict:
+ if 'param' in param_dict and 'value' in param_dict:
+ param_dict[param_dict['param']] = param_dict['value']
+ step.state.inputs.update(param_dict)
+
+
__all__ = [ invoke, WorkflowRunConfig ]
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: guerler: Charts: Fix metadata status
by commits-noreply@bitbucket.org 19 Apr '14
by commits-noreply@bitbucket.org 19 Apr '14
19 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4b430f408ac7/
Changeset: 4b430f408ac7
User: guerler
Date: 2014-04-19 06:53:46
Summary: Charts: Fix metadata status
Affected #: 2 files
diff -r 82605b688d874c0472fd299dbf0485eff10c397f -r 4b430f408ac762a6f2a6856fb199a347bc693fbb config/plugins/visualizations/charts/static/build-app.js
--- a/config/plugins/visualizations/charts/static/build-app.js
+++ b/config/plugins/visualizations/charts/static/build-app.js
@@ -3,4 +3,4 @@
// (c) 2009-2013 Jeremy Ashkenas, DocumentCloud Inc.
// Underscore may be freely distributed under the MIT license.
-(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<div class="'+e.cls+'">'+e.title+"</div>"},value:function(){return options.title}}),i=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),s=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),o=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),u=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),a=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),f=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),c=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),h=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:i,Icon:s,ButtonIcon:o,Input:h,Anchor:u,Message:a,Searchbox:f,Title:l,Text:r,Select:t,ButtonMenu:c}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=this.app.types.get(a);data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Job has been queued..."),t.set("dataset_id_job",n.id),this.app.storage.save(),o._loop(n.id,function(e){switch(e.state){case"ok":return t.state("wait","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),s&&s(),!0;case"running":return t.state("wait","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/datasets/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._get(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.end+"_"+t},_get:function(e,t){e.start||(e.start=0),e.end||(e.end=this.app.config.get("query_limit"));var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f])continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,end:e.end,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){console.debug("Datasets::_fill_from_cache() - Filling request from cache.");for(var t in e.groups){var n=e.groups[t];n.values=[];for(var r in n.columns){var i=n.columns[r],s=this._block_id(e,i.index),o=this.cache[s];for(k in o){var u=n.values[k];u===undefined&&(u={x:parseInt(k)+e.start},n.values[k]=u);var a=o[k];isNaN(a)&&!i.is_label&&(a=0),u[r]=a}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o=0;t.columns&&(o=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+o+" column(s)")),o==0&&console.debug("Datasets::_fetch() - No columns requested");var u="";for(var a in t.columns)u+=t.columns[a]+",";u=u.substring(0,u.length-1);var f=this;e.request("GET",config.root+"api/datasets/"+t.dataset_id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:u},function(e){var t=new Array(o);for(var r=0;r<o;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var s in i){var u=i[s];u!==undefined&&u!=2147483647&&t[s].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/library/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.counter==0)for(var e in this.queue)this.queue[e](),this.queue.splice(e,1)})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},ready:function(){return this.counter==0?!0:!1}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","plugin/library/deferred","mvc/visualization/visualization-model"],function(e,t){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(n){this.groups=new e,this.settings=new Backbone.Model,this.deferred=new t},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({canvas:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,80),this._create_canvas("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":e.hide();break;case"failed":t.addClass("fa fa-warning");break;default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_create_canvas:function(e,t){t=t||1;for(var n in this.canvas)this.canvas[n].remove(),this.canvas.slice(n,0);for(var n=0;n<t;n++){var r=$(this._template_canvas(e,parseInt(100/t)));this.$el.append(r),e=="svg"?this.canvas[n]=d3.select(r[0]):this.canvas[n]=r}},_draw:function(e){var t=this,n=e.deferred.register(),r=e.get("type");this.chart_settings=this.app.types.get(r);var i=this.chart_settings.use_panels,s=1;i&&(s=e.groups.length),this._create_canvas(this.chart_settings.tag,s),e.state("wait","Please wait...");if(!this.chart_settings.execute||this.chart_settings.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+r+"/"+r],function(r){var i=new r(t.app,{canvas:t.canvas});t.chart_settings.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){i.draw(n,e,t._defaultRequestDictionary(e))},function(){e.deferred.done(n)}):i.draw(n,e,t._defaultRequestDictionary(e)):i.draw(n,e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){for(var i in r.chart_settings.columns)t+=i+"_"+ ++n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_settings.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var n=0,r=this;return e.groups.each(function(e){var i={};for(var s in r.chart_settings.columns){var o=r.chart_settings.columns[s];i[s]={index:e.get(s),is_label:o.is_label}}t.groups.push({key:++n+":"+e.get("key"),columns:i})}),t},_template:function(){return'<div style="height: inherit; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_canvas:function(e,t){return"<"+e+' class="canvas" style="float: left; display: block; width:'+t+'%; height: 100%;"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_screenshot:function(){var e=new XMLSerializer,t=e.serializeToString(this.viewport_view.svg.node()),n="data:image/svg+xml;base64,"+btoa(t);window.location.href="data:application/x-download/;charset=utf-8,"+encodeURIComponent(t)},_wait:function(e,t){if(e.deferred.ready())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata...");var l=this.chart.deferred.register();this.app.datasets.request({id:e},function(e){for(var t in s){var n=i.columns[t].is_label,o=[],u=e.metadata_column_types;for(var a in u)(!n&&(u[a]=="int"||u[a]=="float")||n)&&o.push({label:"Column: "+(parseInt(a)+1)+" ["+u[a]+"]",value:a});s[t].update(o),s[t].show()}r.chart.state("wait","Metadata initialized..."),r.chart.deferred.done(l)})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({list:[],initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll(),this.list=[];for(var n in e)this._add(n,e[n],t);for(var n in this.list){var r=this.list[n].options.onchange;r&&r()}},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:e,placeholder:n.placeholder,onchange:function(){r.set(e,s.value())}});break;case"select":s=new t.Select.View({id:e,data:n.data,onchange:function(){var t=s.value();r.set(e,t);var o=_.findWhere(n.data,{value:t});o&&(o.show&&i.$el.find("#"+o.show).fadeIn("fast"),o.hide&&i.$el.find("#"+o.hide).fadeOut("fast"))}});break;case"separator":s=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),u.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(u)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){var u=this;this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}}),this.table=new t.View({header:!1,onchange:function(e){u.chart.settings.clear(),u.chart.set({type:e}),u.chart.set("modified",!0)},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"}),this.table.addHeader("No."),this.table.addHeader("Type"),this.table.addHeader("Library"),this.table.addHeader("Processing*"),this.table.appendHeader();var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),this.table.add(h.title),this.table.add(h.library,"10%"),h.execute?this.table.add((new n.Icon({icon:"fa-check"})).$el,"10%","center"):this.table.add(""),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),p.append((new n.Text({title:"*Certain chart types pre-process data before rendering the visualization. The pre-processing is done using the chartskit available in the Toolshed.",cls:"toolParamHelp"})).$el),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","nvd3_bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel();var e=this;this.chart.deferred.execute(function(){e.app.storage.save(),e.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/nvd3/config",[],function(){return{title:"",library:"nvd3.js",tag:"svg",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"x_axis_tick"},{label:"Auto",value:"auto",hide:"x_axis_tick"},{label:"Float",value:"f",show:"x_axis_tick"},{label:"Exponent",value:"e",show:"x_axis_tick"},{label:"Integer",value:"d",hide:"x_axis_tick"},{label:"Percentage",value:"p",show:"x_axis_tick"},{label:"Rounded",value:"r",show:"x_axis_tick"},{label:"SI-prefix",value:"s",show:"x_axis_tick"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"y_axis_tick"},{label:"Auto",value:"auto",hide:"y_axis_tick"},{label:"Float",value:"f",show:"y_axis_tick"},{label:"Exponent",value:"e",show:"y_axis_tick"},{label:"Integer",value:"d",hide:"y_axis_tick"},{label:"Percentage",value:"p",show:"y_axis_tick"},{label:"Rounded",value:"r",show:"y_axis_tick"},{label:"SI-prefix",value:"s",show:"y_axis_tick"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_bardiagram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/nvd3_histogram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:"histogram",columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_tick:{init:".2"}}})}),define("plugin/charts/nvd3_horizontal/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/nvd3_line/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/nvd3_linewithfocus/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/nvd3_piechart/config",[],function(){return{title:"Pie chart",library:"nvd3.js",tag:"svg",use_panels:!0,columns:{label:{title:"Labels",is_label:!0},y:{title:"Values"}},settings:{show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_scatterplot/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/nvd3_stackedarea/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/highcharts_boxplot/config",[],function(){return{title:"Box plot",library:"highcharts.js",element:"div",execute:"boxplot",columns:{y:{title:"Observations"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"}}}}),define("plugin/charts/types",["plugin/charts/nvd3_bardiagram/config","plugin/charts/nvd3_histogram/config","plugin/charts/nvd3_horizontal/config","plugin/charts/nvd3_line/config","plugin/charts/nvd3_linewithfocus/config","plugin/charts/nvd3_piechart/config","plugin/charts/nvd3_scatterplot/config","plugin/charts/nvd3_stackedarea/config","plugin/charts/highcharts_boxplot/config"],function(e,t,n,r,i,s,o,u,a){return Backbone.Model.extend({defaults:{nvd3_bardiagram:e,nvd3_horizontal:n,nvd3_histogram:t,nvd3_line:r,nvd3_linewithfocus:i,nvd3_piechart:s,nvd3_scatterplot:o,nvd3_stackedarea:u,highcharts_boxplot:a}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.chart.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
+(function(){var e=this,t=e._,n={},r=Array.prototype,i=Object.prototype,s=Function.prototype,o=r.push,u=r.slice,a=r.concat,f=i.toString,l=i.hasOwnProperty,c=r.forEach,h=r.map,p=r.reduce,d=r.reduceRight,v=r.filter,m=r.every,g=r.some,y=r.indexOf,b=r.lastIndexOf,w=Array.isArray,E=Object.keys,S=s.bind,x=function(e){if(e instanceof x)return e;if(!(this instanceof x))return new x(e);this._wrapped=e};typeof exports!="undefined"?(typeof module!="undefined"&&module.exports&&(exports=module.exports=x),exports._=x):e._=x,x.VERSION="1.4.4";var T=x.each=x.forEach=function(e,t,r){if(e==null)return;if(c&&e.forEach===c)e.forEach(t,r);else if(e.length===+e.length){for(var i=0,s=e.length;i<s;i++)if(t.call(r,e[i],i,e)===n)return}else for(var o in e)if(x.has(e,o)&&t.call(r,e[o],o,e)===n)return};x.map=x.collect=function(e,t,n){var r=[];return e==null?r:h&&e.map===h?e.map(t,n):(T(e,function(e,i,s){r.push(t.call(n,e,i,s))}),r)};var N="Reduce of empty array with no initial value";x.reduce=x.foldl=x.inject=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(p&&e.reduce===p)return r&&(t=x.bind(t,r)),i?e.reduce(t,n):e.reduce(t);T(e,function(e,s,o){i?n=t.call(r,n,e,s,o):(n=e,i=!0)});if(!i)throw new TypeError(N);return n},x.reduceRight=x.foldr=function(e,t,n,r){var i=arguments.length>2;e==null&&(e=[]);if(d&&e.reduceRight===d)return r&&(t=x.bind(t,r)),i?e.reduceRight(t,n):e.reduceRight(t);var s=e.length;if(s!==+s){var o=x.keys(e);s=o.length}T(e,function(u,a,f){a=o?o[--s]:--s,i?n=t.call(r,n,e[a],a,f):(n=e[a],i=!0)});if(!i)throw new TypeError(N);return n},x.find=x.detect=function(e,t,n){var r;return C(e,function(e,i,s){if(t.call(n,e,i,s))return r=e,!0}),r},x.filter=x.select=function(e,t,n){var r=[];return e==null?r:v&&e.filter===v?e.filter(t,n):(T(e,function(e,i,s){t.call(n,e,i,s)&&r.push(e)}),r)},x.reject=function(e,t,n){return x.filter(e,function(e,r,i){return!t.call(n,e,r,i)},n)},x.every=x.all=function(e,t,r){t||(t=x.identity);var i=!0;return e==null?i:m&&e.every===m?e.every(t,r):(T(e,function(e,s,o){if(!(i=i&&t.call(r,e,s,o)))return n}),!!i)};var C=x.some=x.any=function(e,t,r){t||(t=x.identity);var i=!1;return e==null?i:g&&e.some===g?e.some(t,r):(T(e,function(e,s,o){if(i||(i=t.call(r,e,s,o)))return n}),!!i)};x.contains=x.include=function(e,t){return e==null?!1:y&&e.indexOf===y?e.indexOf(t)!=-1:C(e,function(e){return e===t})},x.invoke=function(e,t){var n=u.call(arguments,2),r=x.isFunction(t);return x.map(e,function(e){return(r?t:e[t]).apply(e,n)})},x.pluck=function(e,t){return x.map(e,function(e){return e[t]})},x.where=function(e,t,n){return x.isEmpty(t)?n?void 0:[]:x[n?"find":"filter"](e,function(e){for(var n in t)if(t[n]!==e[n])return!1;return!0})},x.findWhere=function(e,t){return x.where(e,t,!0)},x.max=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.max.apply(Math,e);if(!t&&x.isEmpty(e))return-Infinity;var r={computed:-Infinity,value:-Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o>=r.computed&&(r={value:e,computed:o})}),r.value},x.min=function(e,t,n){if(!t&&x.isArray(e)&&e[0]===+e[0]&&e.length<65535)return Math.min.apply(Math,e);if(!t&&x.isEmpty(e))return Infinity;var r={computed:Infinity,value:Infinity};return T(e,function(e,i,s){var o=t?t.call(n,e,i,s):e;o<r.computed&&(r={value:e,computed:o})}),r.value},x.shuffle=function(e){var t,n=0,r=[];return T(e,function(e){t=x.random(n++),r[n-1]=r[t],r[t]=e}),r};var k=function(e){return x.isFunction(e)?e:function(t){return t[e]}};x.sortBy=function(e,t,n){var r=k(t);return x.pluck(x.map(e,function(e,t,i){return{value:e,index:t,criteria:r.call(n,e,t,i)}}).sort(function(e,t){var n=e.criteria,r=t.criteria;if(n!==r){if(n>r||n===void 0)return 1;if(n<r||r===void 0)return-1}return e.index<t.index?-1:1}),"value")};var L=function(e,t,n,r){var i={},s=k(t==null?x.identity:t);return T(e,function(t,o){var u=s.call(n,t,o,e);r(i,u,t)}),i};x.groupBy=function(e,t,n){return L(e,t,n,function(e,t,n){(x.has(e,t)?e[t]:e[t]=[]).push(n)})},x.countBy=function(e,t,n){return L(e,t,n,function(e,t){x.has(e,t)||(e[t]=0),e[t]++})},x.sortedIndex=function(e,t,n,r){n=n==null?x.identity:k(n);var i=n.call(r,t),s=0,o=e.length;while(s<o){var u=s+o>>>1;n.call(r,e[u])<i?s=u+1:o=u}return s},x.toArray=function(e){return e?x.isArray(e)?u.call(e):e.length===+e.length?x.map(e,x.identity):x.values(e):[]},x.size=function(e){return e==null?0:e.length===+e.length?e.length:x.keys(e).length},x.first=x.head=x.take=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,0,t):e[0]},x.initial=function(e,t,n){return u.call(e,0,e.length-(t==null||n?1:t))},x.last=function(e,t,n){return e==null?void 0:t!=null&&!n?u.call(e,Math.max(e.length-t,0)):e[e.length-1]},x.rest=x.tail=x.drop=function(e,t,n){return u.call(e,t==null||n?1:t)},x.compact=function(e){return x.filter(e,x.identity)};var A=function(e,t,n){return T(e,function(e){x.isArray(e)?t?o.apply(n,e):A(e,t,n):n.push(e)}),n};x.flatten=function(e,t){return A(e,t,[])},x.without=function(e){return x.difference(e,u.call(arguments,1))},x.uniq=x.unique=function(e,t,n,r){x.isFunction(t)&&(r=n,n=t,t=!1);var i=n?x.map(e,n,r):e,s=[],o=[];return T(i,function(n,r){if(t?!r||o[o.length-1]!==n:!x.contains(o,n))o.push(n),s.push(e[r])}),s},x.union=function(){return x.uniq(a.apply(r,arguments))},x.intersection=function(e){var t=u.call(arguments,1);return x.filter(x.uniq(e),function(e){return x.every(t,function(t){return x.indexOf(t,e)>=0})})},x.difference=function(e){var t=a.apply(r,u.call(arguments,1));return x.filter(e,function(e){return!x.contains(t,e)})},x.zip=function(){var e=u.call(arguments),t=x.max(x.pluck(e,"length")),n=new Array(t);for(var r=0;r<t;r++)n[r]=x.pluck(e,""+r);return n},x.unzip=function(e){var t=[];return x.each(e,function(e,n){x.each(e,function(e,r){t.length<=r&&(t[r]=[]),t[r][n]=e})}),t},x.object=function(e,t){if(e==null)return{};var n={};for(var r=0,i=e.length;r<i;r++)t?n[e[r]]=t[r]:n[e[r][0]]=e[r][1];return n},x.indexOf=function(e,t,n){if(e==null)return-1;var r=0,i=e.length;if(n){if(typeof n!="number")return r=x.sortedIndex(e,t),e[r]===t?r:-1;r=n<0?Math.max(0,i+n):n}if(y&&e.indexOf===y)return e.indexOf(t,n);for(;r<i;r++)if(e[r]===t)return r;return-1},x.lastIndexOf=function(e,t,n){if(e==null)return-1;var r=n!=null;if(b&&e.lastIndexOf===b)return r?e.lastIndexOf(t,n):e.lastIndexOf(t);var i=r?n:e.length;while(i--)if(e[i]===t)return i;return-1},x.range=function(e,t,n){arguments.length<=1&&(t=e||0,e=0),n=arguments[2]||1;var r=Math.max(Math.ceil((t-e)/n),0),i=0,s=new Array(r);while(i<r)s[i++]=e,e+=n;return s};var O=function(){};x.bind=function(e,t){var n,r;if(e.bind===S&&S)return S.apply(e,u.call(arguments,1));if(!x.isFunction(e))throw new TypeError;return n=u.call(arguments,2),r=function(){if(this instanceof r){O.prototype=e.prototype;var i=new O;O.prototype=null;var s=e.apply(i,n.concat(u.call(arguments)));return Object(s)===s?s:i}return e.apply(t,n.concat(u.call(arguments)))}},x.partial=function(e){var t=u.call(arguments,1);return function(){return e.apply(this,t.concat(u.call(arguments)))}},x.bindAll=function(e){var t=u.call(arguments,1);if(t.length===0)throw new Error("bindAll must be passed function names");return T(t,function(t){e[t]=x.bind(e[t],e)}),e},x.memoize=function(e,t){var n={};return t||(t=x.identity),function(){var r=t.apply(this,arguments);return x.has(n,r)?n[r]:n[r]=e.apply(this,arguments)}},x.delay=function(e,t){var n=u.call(arguments,2);return setTimeout(function(){return e.apply(null,n)},t)},x.defer=function(e){return x.delay.apply(x,[e,1].concat(u.call(arguments,1)))},x.throttle=function(e,t,n){var r,i,s,o,u=0,a=function(){u=new Date,s=null,o=e.apply(r,i)};return function(){var f=new Date;!u&&n===!1&&(u=f);var l=t-(f-u);return r=this,i=arguments,l<=0?(clearTimeout(s),s=null,u=f,o=e.apply(r,i)):s||(s=setTimeout(a,l)),o}},x.debounce=function(e,t,n){var r,i;return function(){var s=this,o=arguments,u=function(){r=null,n||(i=e.apply(s,o))},a=n&&!r;return clearTimeout(r),r=setTimeout(u,t),a&&(i=e.apply(s,o)),i}},x.once=function(e){var t=!1,n;return function(){return t?n:(t=!0,n=e.apply(this,arguments),e=null,n)}},x.wrap=function(e,t){return function(){var n=[e];return o.apply(n,arguments),t.apply(this,n)}},x.compose=function(){var e=arguments;return function(){var t=arguments;for(var n=e.length-1;n>=0;n--)t=[e[n].apply(this,t)];return t[0]}},x.after=function(e,t){return e<=0?t():function(){if(--e<1)return t.apply(this,arguments)}},x.keys=E||function(e){if(e!==Object(e))throw new TypeError("Invalid object");var t=[];for(var n in e)x.has(e,n)&&t.push(n);return t},x.values=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push(e[n]);return t},x.pairs=function(e){var t=[];for(var n in e)x.has(e,n)&&t.push([n,e[n]]);return t},x.invert=function(e){var t={};for(var n in e)x.has(e,n)&&(t[e[n]]=n);return t},x.functions=x.methods=function(e){var t=[];for(var n in e)x.isFunction(e[n])&&t.push(n);return t.sort()},x.extend=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]=t[n]}),e},x.pick=function(e){var t={},n=a.apply(r,u.call(arguments,1));return T(n,function(n){n in e&&(t[n]=e[n])}),t},x.omit=function(e){var t={},n=a.apply(r,u.call(arguments,1));for(var i in e)x.contains(n,i)||(t[i]=e[i]);return t},x.defaults=function(e){return T(u.call(arguments,1),function(t){if(t)for(var n in t)e[n]===void 0&&(e[n]=t[n])}),e},x.clone=function(e){return x.isObject(e)?x.isArray(e)?e.slice():x.extend({},e):e},x.tap=function(e,t){return t(e),e};var M=function(e,t,n,r){if(e===t)return e!==0||1/e==1/t;if(e==null||t==null)return e===t;e instanceof x&&(e=e._wrapped),t instanceof x&&(t=t._wrapped);var i=f.call(e);if(i!=f.call(t))return!1;switch(i){case"[object String]":return e==String(t);case"[object Number]":return e!=+e?t!=+t:e==0?1/e==1/t:e==+t;case"[object Date]":case"[object Boolean]":return+e==+t;case"[object RegExp]":return e.source==t.source&&e.global==t.global&&e.multiline==t.multiline&&e.ignoreCase==t.ignoreCase}if(typeof e!="object"||typeof t!="object")return!1;var s=n.length;while(s--)if(n[s]==e)return r[s]==t;n.push(e),r.push(t);var o=0,u=!0;if(i=="[object Array]"){o=e.length,u=o==t.length;if(u)while(o--)if(!(u=M(e[o],t[o],n,r)))break}else{var a=e.constructor,l=t.constructor;if(a!==l&&!(x.isFunction(a)&&a instanceof a&&x.isFunction(l)&&l instanceof l))return!1;for(var c in e)if(x.has(e,c)){o++;if(!(u=x.has(t,c)&&M(e[c],t[c],n,r)))break}if(u){for(c in t)if(x.has(t,c)&&!(o--))break;u=!o}}return n.pop(),r.pop(),u};x.isEqual=function(e,t){return M(e,t,[],[])},x.isEmpty=function(e){if(e==null)return!0;if(x.isArray(e)||x.isString(e))return e.length===0;for(var t in e)if(x.has(e,t))return!1;return!0},x.isElement=function(e){return!!e&&e.nodeType===1},x.isArray=w||function(e){return f.call(e)=="[object Array]"},x.isObject=function(e){return e===Object(e)},T(["Arguments","Function","String","Number","Date","RegExp"],function(e){x["is"+e]=function(t){return f.call(t)=="[object "+e+"]"}}),x.isArguments(arguments)||(x.isArguments=function(e){return!!e&&!!x.has(e,"callee")}),typeof /./!="function"&&(x.isFunction=function(e){return typeof e=="function"}),x.isFinite=function(e){return isFinite(e)&&!isNaN(parseFloat(e))},x.isNaN=function(e){return x.isNumber(e)&&e!=+e},x.isBoolean=function(e){return e===!0||e===!1||f.call(e)=="[object Boolean]"},x.isNull=function(e){return e===null},x.isUndefined=function(e){return e===void 0},x.has=function(e,t){return l.call(e,t)},x.noConflict=function(){return e._=t,this},x.identity=function(e){return e},x.times=function(e,t,n){var r=Array(e);for(var i=0;i<e;i++)r[i]=t.call(n,i);return r},x.random=function(e,t){return t==null&&(t=e,e=0),e+Math.floor(Math.random()*(t-e+1))};var _={escape:{"&":"&","<":"<",">":">",'"':""","'":"'","/":"/"}};_.unescape=x.invert(_.escape);var D={escape:new RegExp("["+x.keys(_.escape).join("")+"]","g"),unescape:new RegExp("("+x.keys(_.unescape).join("|")+")","g")};x.each(["escape","unescape"],function(e){x[e]=function(t){return t==null?"":(""+t).replace(D[e],function(t){return _[e][t]})}}),x.result=function(e,t){if(e==null)return void 0;var n=e[t];return x.isFunction(n)?n.call(e):n},x.mixin=function(e){T(x.functions(e),function(t){var n=x[t]=e[t];x.prototype[t]=function(){var e=[this._wrapped];return o.apply(e,arguments),F.call(this,n.apply(x,e))}})};var P=0;x.uniqueId=function(e){var t=++P+"";return e?e+t:t},x.templateSettings={evaluate:/<%([\s\S]+?)%>/g,interpolate:/<%=([\s\S]+?)%>/g,escape:/<%-([\s\S]+?)%>/g};var H=/(.)^/,B={"'":"'","\\":"\\","\r":"r","\n":"n"," ":"t","\u2028":"u2028","\u2029":"u2029"},j=/\\|'|\r|\n|\t|\u2028|\u2029/g;x.template=function(e,t,n){var r;n=x.defaults({},n,x.templateSettings);var i=new RegExp([(n.escape||H).source,(n.interpolate||H).source,(n.evaluate||H).source].join("|")+"|$","g"),s=0,o="__p+='";e.replace(i,function(t,n,r,i,u){return o+=e.slice(s,u).replace(j,function(e){return"\\"+B[e]}),n&&(o+="'+\n((__t=("+n+"))==null?'':_.escape(__t))+\n'"),r&&(o+="'+\n((__t=("+r+"))==null?'':__t)+\n'"),i&&(o+="';\n"+i+"\n__p+='"),s=u+t.length,t}),o+="';\n",n.variable||(o="with(obj||{}){\n"+o+"}\n"),o="var __t,__p='',__j=Array.prototype.join,print=function(){__p+=__j.call(arguments,'');};\n"+o+"return __p;\n";try{r=new Function(n.variable||"obj","_",o)}catch(u){throw u.source=o,u}if(t)return r(t,x);var a=function(e){return r.call(this,e,x)};return a.source="function("+(n.variable||"obj")+"){\n"+o+"}",a},x.chain=function(e){return x(e).chain()};var F=function(e){return this._chain?x(e).chain():e};x.mixin(x),T(["pop","push","reverse","shift","sort","splice","unshift"],function(e){var t=r[e];x.prototype[e]=function(){var n=this._wrapped;return t.apply(n,arguments),(e=="shift"||e=="splice")&&n.length===0&&delete n[0],F.call(this,n)}}),T(["concat","join","slice"],function(e){var t=r[e];x.prototype[e]=function(){return F.call(this,t.apply(this._wrapped,arguments))}}),x.extend(x.prototype,{chain:function(){return this._chain=!0,this},value:function(){return this._wrapped}})}).call(this),define("libs/underscore",function(e){return function(){var t,n;return t||e._}}(this)),define("utils/utils",["libs/underscore"],function(e){function t(e,t,r){n("GET",e,{},t,r)}function n(e,t,n,r,i){if(e=="GET"||e=="DELETE")t.indexOf("?")==-1?t+="?":t+="&",t+=$.param(n);var s=new XMLHttpRequest;s.open(e,t,!0),s.setRequestHeader("Accept","application/json"),s.setRequestHeader("Cache-Control","no-cache"),s.setRequestHeader("X-Requested-With","XMLHttpRequest"),s.setRequestHeader("Content-Type","application/json"),s.onloadend=function(){var e=s.status;try{response=jQuery.parseJSON(s.responseText)}catch(t){response=s.responseText}e==200?r&&r(response):i&&i(response)},e=="GET"||e=="DELETE"?s.send():s.send(JSON.stringify(n))}function r(e,t){var n=$('<div class="'+e+'"></div>');n.appendTo(":eq(0)");var r=n.css(t);return n.remove(),r}function i(e){$('link[href^="'+e+'"]').length||$('<link href="'+galaxy_config.root+e+'" rel="stylesheet">').appendTo("head")}function s(t,n){return t?e.defaults(t,n):n}function o(e,t){var n="";if(e>=1e11)e/=1e11,n="TB";else if(e>=1e8)e/=1e8,n="GB";else if(e>=1e5)e/=1e5,n="MB";else if(e>=100)e/=100,n="KB";else{if(!(e>0))return"<strong>-</strong>";e*=10,n="b"}var r=Math.round(e)/10;return t?r+" "+n:"<strong>"+r+"</strong> "+n}function u(){return(new Date).getTime().toString(36)}function a(e){var t=$("<p></p>");return t.append(e),t}function f(){var e=new Date,t=(e.getHours()<10?"0":"")+e.getHours(),n=(e.getMinutes()<10?"0":"")+e.getMinutes(),r=e.getDate()+"/"+(e.getMonth()+1)+"/"+e.getFullYear()+", "+t+":"+n;return r}return{cssLoadFile:i,cssGetAttribute:r,get:t,merge:s,bytesToString:o,uuid:u,time:f,wrap:a,request:n}}),define("mvc/ui/ui-modal",["utils/utils"],function(e){var t=Backbone.View.extend({elMain:"body",optionsDefault:{title:"ui-modal",body:"",backdrop:!0,height:null,width:null,closing_events:!1},buttonList:{},initialize:function(e){e&&this._create(e)},show:function(e){this.initialize(e),this.options.height?(this.$body.css("height",this.options.height),this.$body.css("overflow","hidden")):this.$body.css("max-height",$(window).height()/2),this.options.width&&this.$dialog.css("width",this.options.width),this.visible?this.$el.show():this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.visible=!1,this.$el.fadeOut("fast")},enableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!1)},disableButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).prop("disabled",!0)},showButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).show()},hideButton:function(e){var t=this.buttonList[e];this.$buttons.find("#"+t).hide()},getButton:function(e){var t=this.buttonList[e];return this.$buttons.find("#"+t)},scrollTop:function(){return this.$body.scrollTop()},_create:function(e){var t=this;this.options=_.defaults(e,this.optionsDefault),this.options.body=="progress"&&(this.options.body=$('<div class="progress progress-striped active"><div class="progress-bar progress-bar-info" style="width:100%"></div></div>')),this.$el&&(this.$el.remove(),$(document).off("keyup.ui-modal")),this.setElement(this._template(this.options.title)),this.$dialog=this.$el.find(".modal-dialog"),this.$body=this.$el.find(".modal-body"),this.$footer=this.$el.find(".modal-footer"),this.$buttons=this.$el.find(".buttons"),this.$backdrop=this.$el.find(".modal-backdrop"),this.$body.html(this.options.body),this.options.backdrop||this.$backdrop.removeClass("in");if(this.options.buttons){this.buttonList={};var n=0;$.each(this.options.buttons,function(e,r){var i="button-"+n++;t.$buttons.append($('<button id="'+i+'"></button>').text(e).click(r)).append(" "),t.buttonList[e]=i})}else this.$footer.hide();$(this.elMain).append($(this.el)),this.options.closing_events&&($(document).on("keyup.ui-modal",function(e){e.keyCode==27&&t.hide()}),this.$el.find(".modal-backdrop").on("click",function(){t.hide()}))},_template:function(e){return'<div class="modal"><div class="modal-backdrop fade in" style="z-index: -1;"></div><div class="modal-dialog"><div class="modal-content"><div class="modal-header"><button type="button" class="close" style="display: none;">×</button><h4 class="title">'+e+"</h4>"+"</div>"+'<div class="modal-body" style="position: static;"></div>'+'<div class="modal-footer">'+'<div class="buttons" style="float: right;"></div>'+"</div>"+"</div"+"</div>"+"</div>"}});return{View:t}}),define("mvc/ui/ui-portlet",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,optionsDefault:{title:"",icon:"",buttons:null,body:null,height:null,operations:null,placement:"bottom",overflow:"auto"},$title:null,$content:null,$buttons:null,$operations:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$content=this.$el.find("#content"),this.$title=this.$el.find("#title-text"),this.options.height&&(this.$el.find("#body").css("height",this.options.height),this.$el.find("#content").css("overflow",this.options.overflow)),this.$buttons=$(this.el).find("#buttons");if(this.options.buttons){var n=this;$.each(this.options.buttons,function(e,t){t.$el.prop("id",e),n.$buttons.append(t.$el)})}else this.$buttons.remove();this.$operations=$(this.el).find("#operations");if(this.options.operations){var n=this;$.each(this.options.operations,function(e,t){t.$el.prop("id",e),n.$operations.append(t.$el)})}this.options.body&&this.append(this.options.body)},append:function(t){this.$content.append(e.wrap(t))},content:function(){return this.$content},show:function(){this.$el.fadeIn("fast"),this.visible=!0},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},enableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!1)},disableButton:function(e){this.$buttons.find("#"+e).prop("disabled",!0)},hideOperation:function(e){this.$operations.find("#"+e).hide()},showOperation:function(e){this.$operations.find("#"+e).show()},setOperation:function(e,t){var n=this.$operations.find("#"+e);n.off("click"),n.on("click",t)},title:function(e){var t=this.$title;return e&&t.html(e),t.html()},_template:function(e){var t='<div class="toolForm portlet-view no-highlight">';if(e.title||e.icon)t+='<div id="title" class="toolFormTitle portlet-title"><div id="operations" class="portlet-operations"/><div style="overflow: hidden;">',e.icon&&(t+='<div class="portlet-title-icon fa '+e.icon+'"> </div>'),t+='<div id="title-text" class="portlet-title-text">'+e.title+"</div>",t+="</div></div>";return t+='<div id="body" class="toolFormBody portlet-body">',e.placement=="top"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+='<div id="content" class="portlet-content"/>',e.placement=="bottom"&&(t+='<div id="buttons" class="portlet-buttons"/>'),t+="</div></div>",t}});return{View:t}}),define("plugin/library/ui-select",["utils/utils"],function(e){var t=Backbone.View.extend({optionsDefault:{id:"",cls:"",empty:"No data available",visible:!0,wait:!1},selected:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.$select=this.$el.find("#select"),this.$icon=this.$el.find("#icon"),this.selected=this.options.value;var n=this;this.options.onchange&&this.$select.on("change",function(){n.value(n.$select.val())}),this._refresh(),this.options.visible||this.hide(),this.options.wait?this.wait():this.show()},value:function(e){var t=this.selected;e!==undefined&&(this.selected=e,this.$select.val(e));var n=this.selected;return n&&n!=t&&this.options.onchange&&this.options.onchange(n),n},text:function(){return this.$select.find("option:selected").text()},show:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-caret-down"),this.$select.show(),this.$el.show()},hide:function(){this.$el.hide()},wait:function(){this.$icon.removeClass(),this.$icon.addClass("fa fa-spinner fa-spin"),this.$select.hide()},disabled:function(){return this.$select.is(":disabled")},enable:function(){this.$select.prop("disabled",!1)},disable:function(){this.$select.prop("disabled",!0)},add:function(e){this.$select.append(this._templateOption(e)),this._refresh()},del:function(e){this.$select.find("option[value="+e+"]").remove(),this.$select.trigger("change"),this._refresh()},update:function(e){this.$select.find("option").remove();for(var t in e)this.$select.append(this._templateOption(e[t]));!this.selected&&e.length>0&&this.value(e[0].value),this._refresh()},_refresh:function(){this.$select.find("option[value=null]").remove();var e=this.$select.find("option").length;e==0?(this.$select.append(this._templateOption({value:"null",label:this.options.empty})),this.disable()):(this.enable(),this.selected&&this.$select.val(this.selected))},_exists:function(e){return 0!=this.$select.find("option[value="+e+"]").length},_templateOption:function(e){return'<option value="'+e.value+'">'+e.label+"</option>"},_template:function(e){var t='<div id="'+e.id+'" class="styled-select">'+'<div class="button">'+'<i id="icon"/>'+"</div>"+'<select id="select" class="select '+e.cls+" "+e.id+'">';for(key in e.data){var n=e.data[key],r="";if(n.value==e.value||n.value=="")r="selected";t+='<option value="'+n.value+'" '+r+">"+n.label+"</option>"}return t+="</select></div>",t}});return{View:t}}),define("plugin/library/ui",["utils/utils","plugin/library/ui-select"],function(e,t){var n=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.find("b").html(e)},_template:function(e){return"<label><b>"+e.title+"</b></label>"},value:function(){return options.title}}),r=Backbone.View.extend({optionsDefault:{title:"",cls:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options))},title:function(e){this.$el.html(e)},_template:function(e){return'<div class="'+e.cls+'">'+e.title+"</div>"},value:function(){return options.title}}),i=Backbone.View.extend({optionsDefault:{id:null,title:"","float":"right",cls:"btn-default",icon:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t='<button id="'+e.id+'" type="submit" style="margin-right: 5px; float: '+e.float+';" type="button" class="btn '+e.cls+'">';return e.icon&&(t+='<i class="icon fa '+e.icon+'"></i> '),t+=e.title+"</button>",t}}),s=Backbone.View.extend({optionsDefault:{"float":"right",icon:"",tooltip:"",placement:"bottom",title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){return'<div><span class="fa '+e.icon+'" style="font-size: 1.2em;"/> '+e.title+"</div>"}}),o=Backbone.View.extend({optionsDefault:{title:"",id:null,"float":"right",cls:"icon-btn",icon:"",tooltip:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick),$(this.el).tooltip({title:t.tooltip,placement:"bottom"})},_template:function(e){var t="";e.title&&(t="width: auto;");var n='<div id="'+e.id+'" style="margin-right: 5px; float: '+e.float+"; "+t+'" class="'+e.cls+'">';return e.title?n+='<div style="margin-right: 5px; margin-left: 5px;"><i class="icon fa '+e.icon+'"/> '+'<span style="position: relative; font-size: 0.8em; font-weight: normal; top: -1px;">'+e.title+"</span>"+"</div>":n+='<i class="icon fa '+e.icon+'"/>',n+="</div>",n}}),u=Backbone.View.extend({optionsDefault:{title:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),$(this.el).on("click",t.onclick)},_template:function(e){return'<div><a href="javascript:void(0)">'+e.title+"</a></div>"}}),a=Backbone.View.extend({optionsDefault:{message:"",status:"info",persistent:!1},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement("<div></div>")},update:function(t){this.options=e.merge(t,this.optionsDefault);if(t.message!=""){this.$el.html(this._template(this.options)),this.$el.fadeIn();if(!t.persistent){var n=this;window.setTimeout(function(){n.$el.is(":visible")?n.$el.fadeOut():n.$el.hide()},3e3)}}else this.$el.fadeOut()},_template:function(e){return'<div class="alert alert-'+e.status+'" style="padding: 2px 2px 2px 10px;">'+e.message+"</div>"}}),f=Backbone.View.extend({optionsDefault:{onclick:null,searchword:""},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options));var n=this;this.options.onclick&&this.$el.on("submit",function(e){var t=n.$el.find("#search");n.options.onclick(t.val())})},_template:function(e){return'<div class="search"><form onsubmit="return false;"><input id="search" class="form-control input-sm" type="text" name="search" placeholder="Search..." value="'+e.searchword+'">'+'<button type="submit" class="btn search-btn">'+'<i class="fa fa-search"></i>'+"</button>"+"</form>"+"</div>"}}),l=Backbone.View.extend({optionsDefault:{title:"Unlabeled",body:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.body&&this.$el.find(".body").append(this.options.body)},_template:function(e){return'<div id="title" class="title">'+e.title+":"+"</div>"}}),c=Backbone.View.extend({optionsDefault:{id:"",title:"",target:"",href:"",onunload:null,onclick:null,visible:!0,icon:null,tag:""},$menu:null,initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement($(this._template(this.options)));var n=$(this.el).find(".root"),r=this;n.on("click",function(e){e.preventDefault(),r.options.onclick&&r.options.onclick()}),this.options.visible||this.hide()},show:function(){$(this.el).show()},hide:function(){$(this.el).hide()},addMenu:function(t){var n={title:"",target:"",href:"",onclick:null,divider:!1,icon:null};n=e.merge(t,n),this.$menu||($(this.el).append(this._templateMenu()),this.$menu=$(this.el).find(".menu"));var r=$(this._templateMenuItem(n));r.on("click",function(e){e.preventDefault(),n.onclick&&n.onclick()}),this.$menu.append(r),n.divider&&this.$menu.append($(this._templateDivider()))},_templateMenuItem:function(e){var t='<li><a href="'+e.href+'" target="'+e.target+'">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),t+=" "+e.title+"</a>"+"</li>",t},_templateMenu:function(){return'<ul class="menu dropdown-menu pull-right" role="menu"></ul>'},_templateDivider:function(){return'<li class="divider"></li>'},_template:function(e){var t='<div id="'+e.id+'" class="button-menu btn-group">'+'<button type="button" class="root btn btn-default dropdown-toggle" data-toggle="dropdown">';return e.icon&&(t+='<i class="fa '+e.icon+'"></i>'),"</button></div>",t}}),h=Backbone.View.extend({optionsDefault:{value:"",type:"text",placeholder:"",disabled:!1,visible:!0},initialize:function(t){this.options=e.merge(t,this.optionsDefault),this.setElement(this._template(this.options)),this.options.disabled&&this.$el.prop("disabled",!0),this.options.visible||this.$el.hide();var n=this;this.options.onchange&&this.$el.on("input",function(){n.options.onchange()})},value:function(e){return e!==undefined&&this.$el.val(e),this.$el.val()},_template:function(e){return'<input id="'+e.id+'" type="'+e.type+'" value="'+e.value+'" placeholder="'+e.placeholder+'" class="form-control">'}});return{Label:n,Button:i,Icon:s,ButtonIcon:o,Input:h,Anchor:u,Message:a,Searchbox:f,Title:l,Text:r,Select:t,ButtonMenu:c}}),define("plugin/library/jobs",["utils/utils"],function(e){return Backbone.Model.extend({initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},cleanup:function(t){var n=t.get("dataset_id_job");if(n!=""){var r=this;e.request("PUT",config.root+"api/histories/none/contents/"+n,{deleted:!0},function(){r._refreshHdas()}),t.set("dataset_id_job","")}},submit:function(t,n,r,i,s){var o=this,u=t.id,a=t.get("type"),f=this.app.types.get(a);data={tool_id:"charts",inputs:{input:{id:t.get("dataset_id"),src:"hda"},module:f.execute,columns:r,settings:n}},t.state("wait","Sending job request..."),e.request("POST",config.root+"api/tools",data,function(e){if(!e.outputs||e.outputs.length==0)t.state("failed","Job submission failed. No response."),s&&s();else{o._refreshHdas();var n=e.outputs[0];t.state("wait","Job has been queued..."),t.set("dataset_id_job",n.id),this.app.storage.save(),o._loop(n.id,function(e){switch(e.state){case"ok":return t.state("wait","Job completed successfully..."),i(e),!0;case"error":return t.state("failed","Job has failed. Please check the history for details."),s&&s(),!0;case"running":return t.state("wait","Job is running..."),!1}})}},function(e){var n="";e&&e.message&&e.message.data&&e.message.data.input&&(n=e.message.data.input+"."),t.state("failed","This visualization requires the 'charts' tool. Please make sure it is installed. "+n),s&&s()})},_loop:function(t,n){var r=this;e.request("GET",config.root+"api/datasets/"+t,{},function(e){n(e)||setTimeout(function(){r._loop(t,n)},r.app.config.get("query_timeout"))})},_refreshHdas:function(){Galaxy&&Galaxy.currHistoryPanel&&Galaxy.currHistoryPanel.refreshHdas()}})}),define("plugin/library/datasets",["utils/utils"],function(e){return Backbone.Collection.extend({list:{},cache:{},initialize:function(t,n){this.app=t,this.options=e.merge(n,this.optionsDefault)},request:function(t,n,r){var i=this;if(t.groups)this._get(t,n);else{var s=this.list[t.id];if(s){n(s);return}e.request("GET",config.root+"api/datasets/"+t.id,{},function(e){switch(e.state){case"error":r&&r(e);break;default:i.list[t.id]=e,n(e)}})}},_block_id:function(e,t){return e.id+"_"+e.start+"_"+e.end+"_"+t},_get:function(e,t){e.start||(e.start=0),e.end||(e.end=this.app.config.get("query_limit"));var n=[],r={},i=0;for(var s in e.groups){var o=e.groups[s];for(var u in o.columns){var a=o.columns[u].index,f=this._block_id(e,a);if(this.cache[f])continue;!r[a]&&a!==undefined&&(r[a]=i,n.push(a),i++)}}if(n.length==0){this._fill_from_cache(e),t(e);return}var l={dataset_id:e.id,start:e.start,end:e.end,columns:n},c=this;this._fetch(l,function(r){for(var i in r){var s=n[i],o=c._block_id(e,s);c.cache[o]=r[i]}c._fill_from_cache(e),t(e)})},_fill_from_cache:function(e){console.debug("Datasets::_fill_from_cache() - Filling request from cache.");for(var t in e.groups){var n=e.groups[t];n.values=[];for(var r in n.columns){var i=n.columns[r],s=this._block_id(e,i.index),o=this.cache[s];for(k in o){var u=n.values[k];u===undefined&&(u={x:parseInt(k)+e.start},n.values[k]=u);var a=o[k];isNaN(a)&&!i.is_label&&(a=0),u[r]=a}}}},_fetch:function(t,n){var r=t.start?t.start:0,i=Math.abs(t.end-t.start),s=this.app.config.get("query_limit");if(!i||i>s)i=s;var o=0;t.columns&&(o=t.columns.length,console.debug("Datasets::_fetch() - Fetching "+o+" column(s)")),o==0&&console.debug("Datasets::_fetch() - No columns requested");var u="";for(var a in t.columns)u+=t.columns[a]+",";u=u.substring(0,u.length-1);var f=this;e.request("GET",config.root+"api/datasets/"+t.dataset_id,{data_type:"raw_data",provider:"dataset-column",limit:i,offset:r,indeces:u},function(e){var t=new Array(o);for(var r=0;r<o;r++)t[r]=[];for(var r in e.data){var i=e.data[r];for(var s in i){var u=i[s];u!==undefined&&u!=2147483647&&t[s].push(u)}}console.debug("Datasets::_fetch() - Fetching complete."),n(t)})}})}),define("plugin/models/group",[],function(){return Backbone.Model.extend({defaults:{key:"Data label",date:""},reset:function(){this.clear({silent:!0}).set(this.defaults),this.trigger("reset",this)}})}),define("plugin/models/groups",["plugin/models/group"],function(e){return Backbone.Collection.extend({model:e})}),define("plugin/library/deferred",["utils/utils"],function(e){return Backbone.Model.extend({queue:[],process:{},counter:0,initialize:function(){this.on("refresh",function(){if(this.counter==0)for(var e in this.queue)this.queue[e](),this.queue.splice(e,1)})},execute:function(e){this.queue.push(e),this.trigger("refresh")},register:function(){var t=e.uuid();return this.process[t]=!0,this.counter++,console.debug("Deferred:register() - Registering "+t),t},done:function(e){this.process[e]&&(delete this.process[e],this.counter--,console.debug("Deferred:done() - Unregistering "+e),this.trigger("refresh"))},ready:function(){return this.counter==0?!0:!1}})});var Visualization=Backbone.Model.extend({defaults:{config:{}},urlRoot:function(){var e="/api/visualizations";return window.galaxy_config&&galaxy_config.root?galaxy_config.root+e:e},initialize:function(e){_.isObject(e.config)&&_.isObject(this.defaults.config)&&_.defaults(e.config,this.defaults.config),this._setUpListeners()},_setUpListeners:function(){},set:function(e,t){if(e==="config"){var n=this.get("config");_.isObject(n)&&(t=_.extend(_.clone(n),t))}return Backbone.Model.prototype.set.call(this,e,t),this},toString:function(){var e=this.get("id")||"";return this.get("title")&&(e+=":"+this.get("title")),"Visualization("+e+")"}}),VisualizationCollection=Backbone.Collection.extend({model:Visualization,url:function(){return galaxy_config.root+"api/visualizations"},initialize:function(e,t){t=t||{}},set:function(e,t){var n=this;e=_.map(e,function(e){var t=n.get(e.id);if(!t)return e;var r=t.toJSON();return _.extend(r,e),r}),Backbone.Collection.prototype.set.call(this,e,t)},toString:function(){return["VisualizationCollection(",[this.historyId,this.length].join(),")"].join("")}});define("mvc/visualization/visualization-model",function(){}),define("plugin/models/chart",["plugin/models/groups","plugin/library/deferred","mvc/visualization/visualization-model"],function(e,t){return Backbone.Model.extend({defaults:{id:null,title:"",type:"",date:null,state:"",state_info:"",modified:!1,dataset_id:"",dataset_id_job:""},initialize:function(n){this.groups=new e,this.settings=new Backbone.Model,this.deferred=new t},reset:function(){this.clear({silent:!0}).set(this.defaults),this.groups.reset(),this.settings.clear(),this.trigger("reset",this)},copy:function(e){var t=this;t.clear({silent:!0}).set(this.defaults),t.set(e.attributes),t.settings=e.settings.clone(),t.groups.reset(),e.groups.each(function(e){t.groups.add(e.clone())}),t.trigger("change",t)},state:function(e,t){this.set("state",e),this.set("state_info",t),this.trigger("set:state"),console.debug("Chart:state() - "+t+" ("+e+")")}})}),define("plugin/library/storage",["utils/utils","plugin/models/chart","plugin/models/group"],function(e,t,n){return Backbone.Model.extend({vis:null,initialize:function(e){this.app=e,this.chart=this.app.chart,this.options=this.app.options,this.id=this.options.id,this.vis=new Visualization({type:"charts",config:{dataset_id:this.options.config.dataset_id,chart_dict:{}}}),this.id&&(this.vis.id=this.id);var t=this.options.config.chart_dict;t&&(this.vis.get("config").chart_dict=t)},save:function(){var e=this.app.chart;this.vis.get("config").chart_dict={};var t=e.get("title");t!=""&&this.vis.set("title",t);var n={attributes:e.attributes,settings:e.settings.attributes,groups:[]};e.groups.each(function(e){n.groups.push(e.attributes)}),this.vis.get("config").chart_dict=n;var r=this;this.vis.save().fail(function(e,t,n){console.error(e,t,n)}).then(function(e){e&&e.id&&(r.id=e.id)})},load:function(){var e=this.vis.get("config").chart_dict;if(!e.attributes)return!1;this.chart.set(e.attributes),this.chart.state("ok","Loading saved visualization..."),this.chart.settings.set(e.settings);for(var t in e.groups)this.chart.groups.add(new n(e.groups[t]));return this.chart.set("modified",!1),!0}})}),define("plugin/views/viewport",["mvc/ui/ui-portlet","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({canvas:[],initialize:function(e,t){this.app=e,this.chart=this.app.chart,this.options=n.merge(t,this.optionsDefault),this.setElement($(this._template())),this._fullscreen(this.$el,80),this._create_canvas("div");var r=this;this.chart.on("redraw",function(){r._draw(r.chart)}),this.chart.on("set:state",function(){var e=r.$el.find("#info"),t=e.find("#icon");t.removeClass(),e.show(),e.find("#text").html(r.chart.get("state_info"));var n=r.chart.get("state");switch(n){case"ok":e.hide();break;case"failed":t.addClass("fa fa-warning");break;default:t.addClass("fa fa-spinner fa-spin")}})},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_fullscreen:function(e,t){e.css("height",$(window).height()-t),$(window).resize(function(){e.css("height",$(window).height()-t)})},_create_canvas:function(e,t){t=t||1;for(var n in this.canvas)this.canvas[n].remove(),this.canvas.slice(n,0);for(var n=0;n<t;n++){var r=$(this._template_canvas(e,parseInt(100/t)));this.$el.append(r),e=="svg"?this.canvas[n]=d3.select(r[0]):this.canvas[n]=r}},_draw:function(e){var t=this,n=e.deferred.register(),r=e.get("type");this.chart_settings=this.app.types.get(r);var i=this.chart_settings.use_panels,s=1;i&&(s=e.groups.length),this._create_canvas(this.chart_settings.tag,s),e.state("wait","Please wait...");if(!this.chart_settings.execute||this.chart_settings.execute&&e.get("modified"))this.app.jobs.cleanup(e),e.set("modified",!1);var t=this;require(["plugin/charts/"+r+"/"+r],function(r){var i=new r(t.app,{canvas:t.canvas});t.chart_settings.execute?e.get("dataset_id_job")==""?t.app.jobs.submit(e,t._defaultSettingsString(e),t._defaultRequestString(e),function(){i.draw(n,e,t._defaultRequestDictionary(e))},function(){e.deferred.done(n)}):i.draw(n,e,t._defaultRequestDictionary(e)):i.draw(n,e,t._defaultRequestDictionary(e))})},_defaultRequestString:function(e){var t="",n=0,r=this;return e.groups.each(function(e){for(var i in r.chart_settings.columns)t+=i+"_"+ ++n+":"+(parseInt(e.get(i))+1)+", "}),t.substring(0,t.length-2)},_defaultSettingsString:function(e){var t="";for(key in e.settings.attributes)t+=key+":"+e.settings.get(key)+", ";return t.substring(0,t.length-2)},_defaultRequestDictionary:function(e){var t={groups:[]};this.chart_settings.execute?t.id=e.get("dataset_id_job"):t.id=e.get("dataset_id");var n=0,r=this;return e.groups.each(function(e){var i={};for(var s in r.chart_settings.columns){var o=r.chart_settings.columns[s];i[s]={index:e.get(s),is_label:o.is_label}}t.groups.push({key:++n+":"+e.get("key"),columns:i})}),t},_template:function(){return'<div style="height: inherit; min-height: 50px;"><div id="info" style="position: absolute; margin-left: 10px; margin-top: 10px; margin-bottom: 50px;"><span id="icon" style="font-size: 1.2em; display: inline-block;"/><span id="text" style="position: relative; margin-left: 5px; top: -1px; font-size: 1.0em;"/></div></div>'},_template_canvas:function(e,t){return"<"+e+' class="canvas" style="float: left; display: block; width:'+t+'%; height: 100%;"/>'}})}),define("plugin/views/viewer",["utils/utils","plugin/library/ui","mvc/ui/ui-portlet","plugin/models/group","plugin/views/viewport"],function(e,t,n,r,i){return Backbone.View.extend({initialize:function(e,r){this.app=e,this.chart=this.app.chart,this.viewport_view=new i(e);var s=this;this.portlet=new n.View({icon:"fa-bar-chart-o",title:"Viewport",operations:{edit_button:new t.ButtonIcon({icon:"fa-edit",tooltip:"Customize this chart",title:"Editor",onclick:function(){s._wait(s.chart,function(){s.app.go("editor")})}})}}),this.portlet.append(this.viewport_view.$el),this.setElement(this.portlet.$el);var s=this;this.chart.on("change:title",function(){s._refreshTitle()})},show:function(){this.$el.show(),$(window).trigger("resize")},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e)},_screenshot:function(){var e=new XMLSerializer,t=e.serializeToString(this.viewport_view.svg.node()),n="data:image/svg+xml;base64,"+btoa(t);window.location.href="data:application/x-download/;charset=utf-8,"+encodeURIComponent(t)},_wait:function(e,t){if(e.deferred.ready())t();else{var n=this;this.app.modal.show({title:"Please wait!",body:"Your chart is currently being processed. Please wait and try again.",buttons:{Close:function(){n.app.modal.hide()},Retry:function(){n.app.modal.hide(),setTimeout(function(){n._wait(e,t)},n.app.config.get("query_timeout"))}}})}}})}),define("mvc/ui/ui-tabs",["utils/utils"],function(e){var t=Backbone.View.extend({visible:!1,list:{},$nav:null,$content:null,first_tab:null,optionsDefault:{title_new:"",operations:null,onnew:null},initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(this.options));this.$nav=n.find(".tab-navigation"),this.$content=n.find(".tab-content"),this.setElement(n),this.list={};var r=this;this.options.operations&&$.each(this.options.operations,function(e,t){t.$el.prop("id",e),r.$nav.find(".operations").append(t.$el)});if(this.options.onnew){var i=$(this._template_tab_new(this.options));this.$nav.append(i),i.tooltip({title:"Add a new tab",placement:"bottom",container:r.$el}),i.on("click",function(e){i.tooltip("hide"),r.options.onnew()})}},add:function(e){var t=e.id,n={$title:$(this._template_tab(e)),$content:$(this._template_tab_content(e)),removable:e.ondel?!0:!1};this.list[t]=n,this.options.onnew?this.$nav.find("#new-tab").before(n.$title):this.$nav.append(n.$title),n.$content.append(e.$el),this.$content.append(n.$content),_.size(this.list)==1&&(n.$title.addClass("active"),n.$content.addClass("active"),this.first_tab=t);if(e.ondel){var r=this,i=n.$title.find("#delete");i.tooltip({title:"Delete this tab",placement:"bottom",container:r.$el}),i.on("click",function(){return i.tooltip("destroy"),r.$el.find(".tooltip").remove(),e.ondel(),!1})}e.onclick&&n.$title.on("click",function(){e.onclick()})},del:function(e){var t=this.list[e];t.$title.remove(),t.$content.remove(),delete t,this.first_tab==e&&(this.first_tab=null),this.first_tab!=null&&this.show(this.first_tab)},delRemovable:function(){for(var e in this.list){var t=this.list[e];t.removable&&this.del(e)}},show:function(e){this.$el.fadeIn("fast"),this.visible=!0,e&&this.list[e].$title.find("a").tab("show")},hide:function(){this.$el.fadeOut("fast"),this.visible=!1},hideOperation:function(e){this.$nav.find("#"+e).hide()},showOperation:function(e){this.$nav.find("#"+e).show()},setOperation:function(e,t){var n=this.$nav.find("#"+e);n.off("click"),n.on("click",t)},title:function(e,t){var n=this.list[e].$title.find("#text");return t&&n.html(t),n.html()},_template:function(e){return'<div class="tabbable tabs-left"><ul class="tab-navigation nav nav-tabs"><div class="operations" style="float: right; margin-bottom: 4px;"></div></ul><div class="tab-content"/></div>'},_template_tab_new:function(e){return'<li id="new-tab"><a href="javascript:void(0);"><i style="font-size: 0.8em; margin-right: 5px;" class="fa fa-plus-circle"/>'+e.title_new+"</a>"+"</li>"},_template_tab:function(e){var t='<li id="title-'+e.id+'">'+'<a title="" href="#tab-'+e.id+'" data-toggle="tab" data-original-title="">'+'<span id="text">'+e.title+"</span>";return e.ondel&&(t+='<i id="delete" style="font-size: 0.8em; margin-left: 5px; cursor: pointer;" class="fa fa-minus-circle"/>'),t+="</a></li>",t},_template_tab_content:function(e){return'<div id="tab-'+e.id+'" class="tab-pane"/>'}});return{View:t}}),define("plugin/library/ui-table",["utils/utils"],function(e){var t=Backbone.View.extend({row:null,row_count:0,optionsDefault:{content:"No content available.",onchange:null,ondblclick:null,onconfirm:null},events:{click:"_onclick",dblclick:"_ondblclick"},first:!0,initialize:function(t){this.options=e.merge(t,this.optionsDefault);var n=$(this._template(t));this.$thead=n.find("thead"),this.$tbody=n.find("tbody"),this.$tmessage=n.find("tmessage"),this.setElement(n),this.row=$("<tr></tr>")},addHeader:function(e){var t=$("<th></th>");t.append(e),this.row.append(t)},appendHeader:function(){this.$thead.append(this.row),this.row=$("<tr></tr>")},add:function(e,t,n){var r=$("<td></td>");t&&r.css("width",t),n&&r.css("text-align",n),r.append(e),this.row.append(r)},append:function(e){this._commit(e)},prepend:function(e){this._commit(e,!0)},remove:function(e){var t=this.$tbody.find("#"+e);t.length>0&&(t.remove(),this.row_count--,this._refresh())},removeAll:function(){this.$tbody.html(""),this.row_count=0,this._refresh()},value:function(e){this.before=this.$tbody.find(".current").attr("id"),e!==undefined&&(this.$tbody.find("tr").removeClass("current"),e&&this.$tbody.find("#"+e).addClass("current"));var t=this.$tbody.find(".current").attr("id");return t===undefined?null:(t!=this.before&&this.options.onchange&&this.options.onchange(e),t)},size:function(){return this.$tbody.find("tr").length},_commit:function(e,t){this.remove(e),this.row.attr("id",e),t?this.$tbody.prepend(this.row):this.$tbody.append(this.row),this.row=$("<tr></tr>"),this.row_count++,this._refresh()},_onclick:function(e){var t=this.value(),n=$(e.target).closest("tr").attr("id");n&&t!=n&&(this.options.onconfirm?this.options.onconfirm(n):this.value(n))},_ondblclick:function(e){var t=this.value();t&&this.options.ondblclick&&this.options.ondblclick(t)},_refresh:function(){this.row_count==0?this.$tmessage.show():this.$tmessage.hide()},_template:function(e){return'<div><table class="grid"><thead></thead><tbody style="cursor: pointer;"></tbody></table><tmessage>'+e.content+"</tmessage>"+"<div>"}});return{View:t}}),define("plugin/views/group",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(r,i){this.app=r;var s=this;this.chart=this.app.chart,this.group=i.group,this.group_key=new t.Input({placeholder:"Data label",onchange:function(){s.group.set("key",s.group_key.value())}}),this.table=new e.View({content:"No data column."});var o=$("<div/>");o.append(n.wrap((new t.Label({title:"Provide a label:"})).$el)),o.append(n.wrap(this.group_key.$el)),o.append(n.wrap((new t.Label({title:"Select columns:"})).$el)),o.append(n.wrap(this.table.$el)),this.setElement(o);var s=this;this.chart.on("change:dataset_id",function(){s._refreshTable()}),this.chart.on("change:type",function(){s._refreshTable()}),this.group.on("change:key",function(){s._refreshGroupKey()}),this.group.on("change",function(){s._refreshGroup()}),this._refreshTable(),this._refreshGroupKey(),this._refreshGroup()},_refreshTable:function(){var e=this.chart.get("dataset_id"),n=this.chart.get("type");if(!e||!n)return;var r=this,i=this.app.types.get(n);this.table.removeAll();var s={};for(var o in i.columns){var u=this.group.get(o);u||this.group.set(o,0);var a=i.columns[o],f=new t.Select.View({id:"select_"+o,gid:o,onchange:function(e){r.group.set(this.gid,e),r.chart.set("modified",!0)},value:u,wait:!0});this.table.add(a.title,"25%"),this.table.add(f.$el),this.table.append(o),s[o]=f}this.chart.state("wait","Loading metadata...");var l=this.chart.deferred.register();this.app.datasets.request({id:e},function(e){for(var t in s){var n=i.columns[t].is_label,o=[],u=e.metadata_column_types;for(var a in u)(!n&&(u[a]=="int"||u[a]=="float")||n)&&o.push({label:"Column: "+(parseInt(a)+1)+" ["+u[a]+"]",value:a});s[t].update(o),s[t].show()}r.chart.state("ok","Metadata initialized..."),r.chart.deferred.done(l)})},_refreshGroup:function(){this.group.set("date",n.time())},_refreshGroupKey:function(){var e=this.group.get("key");e===undefined&&(e=""),this.group_key.value(e)}})}),define("plugin/library/ui-table-form",["plugin/library/ui-table","plugin/library/ui","utils/utils"],function(e,t,n){var r=Backbone.View.extend({list:[],initialize:function(r){this.table_title=new t.Label({title:r.title}),this.table=new e.View({content:r.content});var i=$("<div/>");i.append(n.wrap(this.table_title.$el)),i.append(n.wrap(this.table.$el)),this.setElement(i)},title:function(e){this.table_title.title(e)},update:function(e,t){this.table.removeAll(),this.list=[];for(var n in e)this._add(n,e[n],t);for(var n in this.list){var r=this.list[n].options.onchange;r&&r()}},_add:function(e,n,r){var i=this,s=null,o=n.type;switch(o){case"text":s=new t.Input({id:e,placeholder:n.placeholder,onchange:function(){r.set(e,s.value())}});break;case"select":s=new t.Select.View({id:e,data:n.data,onchange:function(){var t=s.value();r.set(e,t);var o=_.findWhere(n.data,{value:t});o&&(o.show&&i.$el.find("#"+o.show).fadeIn("fast"),o.hide&&i.$el.find("#"+o.hide).fadeOut("fast"))}});break;case"separator":s=$("<div/>");break;default:console.log("ui-table-form:_add","Unknown setting type ("+n.type+")");return}if(o!="separator"){r.get(e)||r.set(e,n.init),s.value(r.get(e)),this.list[e]=s;var u=$("<div/>");u.append(s.$el),u.append('<div class="toolParamHelp" style="font-size: 0.9em;">'+n.info+"</div>"),this.table.add('<span style="white-space: nowrap;">'+n.title+"</span>","25%"),this.table.add(u)}else this.table.add('<h6 style="white-space: nowrap;">'+n.title+":<h6/>"),this.table.add($("<div/>"));this.table.append(e)}});return{View:r}}),define("plugin/views/settings",["plugin/library/ui","plugin/library/ui-table-form","utils/utils"],function(e,t,n){return Backbone.View.extend({initialize:function(e,n){this.app=e;var r=this;this.chart=this.app.chart,this.form=new t.View({title:"Chart options:",content:"This chart type does not provide any options."}),this.setElement(this.form.$el);var r=this;this.chart.on("change",function(){r._refreshTable()})},_refreshTable:function(){var e=this.chart.get("type");if(!e)return;var t=this.app.types.get(e);this.form.title(t.title+":"),this.form.update(t.settings,this.chart.settings)}})}),define("plugin/views/editor",["mvc/ui/ui-tabs","plugin/library/ui-table","plugin/library/ui","mvc/ui/ui-portlet","utils/utils","plugin/models/chart","plugin/models/group","plugin/views/group","plugin/views/settings"],function(e,t,n,r,i,s,o,u,a){return Backbone.View.extend({optionsDefault:{header:!0,content:"No content available."},initialize:function(s,o){var u=this;this.app=s,this.chart=this.app.chart,this.options=i.merge(o,this.optionsDefault),this.portlet=new r.View({icon:"fa-bar-chart-o",title:"Editor",operations:{save:new n.ButtonIcon({icon:"fa-save",tooltip:"Draw Chart",title:"Draw",onclick:function(){u.app.go("viewer"),u._saveChart()}}),back:new n.ButtonIcon({icon:"fa-caret-left",tooltip:"Return to Viewer",title:"Return",onclick:function(){u.app.go("viewer"),u.app.storage.load()}})}}),this.table=new t.View({header:!1,onchange:function(e){u.chart.settings.clear(),u.chart.set({type:e}),u.chart.set("modified",!0)},ondblclick:function(e){u.tabs.show("settings")},content:"No chart types available"}),this.table.addHeader("No."),this.table.addHeader("Type"),this.table.addHeader("Library"),this.table.addHeader("Processing*"),this.table.appendHeader();var f=0,l=s.types.attributes;for(var c in l){var h=l[c];this.table.add(++f+"."),this.table.add(h.title),this.table.add(h.library,"10%"),h.execute?this.table.add((new n.Icon({icon:"fa-check"})).$el,"10%","center"):this.table.add(""),this.table.append(c)}this.tabs=new e.View({title_new:"Add Data",onnew:function(){var e=u._addGroupModel();u.tabs.show(e.id)}}),this.title=new n.Input({placeholder:"Chart title",onchange:function(){u.chart.set("title",u.title.value())}});var p=$("<div/>");p.append(i.wrap((new n.Label({title:"Provide a chart title:"})).$el)),p.append(i.wrap(this.title.$el)),p.append(i.wrap((new n.Label({title:"Select a chart type:"})).$el)),p.append(i.wrap(this.table.$el)),p.append((new n.Text({title:"*Certain chart types pre-process data before rendering the visualization. The pre-processing is done using the chartskit available in the Toolshed.",cls:"toolParamHelp"})).$el),this.tabs.add({id:"main",title:"Start",$el:p}),this.settings=new a(this.app),this.tabs.add({id:"settings",title:"Configuration",$el:this.settings.$el}),this.portlet.append(this.tabs.$el),this.setElement(this.portlet.$el),this.tabs.hideOperation("back");var u=this;this.chart.on("change:title",function(e){u._refreshTitle()}),this.chart.on("change:type",function(e){u.table.value(e.get("type"))}),this.chart.on("reset",function(e){u._resetChart()}),this.app.chart.on("redraw",function(e){u.portlet.showOperation("back")}),this.app.chart.groups.on("add",function(e){u._addGroup(e)}),this.app.chart.groups.on("remove",function(e){u._removeGroup(e)}),this.app.chart.groups.on("reset",function(e){u._removeAllGroups()}),this.app.chart.groups.on("change:key",function(e){u._refreshGroupKey()}),this._resetChart()},show:function(){this.$el.show()},hide:function(){this.$el.hide()},_refreshTitle:function(){var e=this.chart.get("title");this.portlet.title(e),this.title.value(e)},_refreshGroupKey:function(){var e=this,t=0;this.chart.groups.each(function(n){var r=n.get("key","");r==""&&(r="Chart data"),e.tabs.title(n.id,++t+": "+r)})},_addGroupModel:function(){var e=new o({id:i.uuid()});return this.chart.groups.add(e),e},_addGroup:function(e){var t=this,n=new u(this.app,{group:e}),r=t.chart.groups.length;this.tabs.add({id:e.id,$el:n.$el,ondel:function(){t.chart.groups.remove(e.id)}}),this._refreshGroupKey()},_removeGroup:function(e){this.tabs.del(e.id),this._refreshGroupKey(),this.chart.set("modified",!0)},_removeAllGroups:function(e){this.tabs.delRemovable()},_resetChart:function(){this.chart.set("id",i.uuid()),this.chart.set("type","nvd3_bardiagram"),this.chart.set("dataset_id",this.app.options.config.dataset_id),this.chart.set("title","New Chart"),this.portlet.hideOperation("back")},_saveChart:function(){this.chart.set({type:this.table.value(),title:this.title.value(),date:i.time()}),this.chart.groups.length==0&&this._addGroupModel();var e=this;this.chart.deferred.execute(function(){e.app.storage.save(),e.chart.trigger("redraw")})}})}),define("plugin/models/config",[],function(){return Backbone.Model.extend({defaults:{query_limit:1e3,query_timeout:500}})}),define("plugin/charts/nvd3/config",[],function(){return{title:"",library:"nvd3.js",tag:"svg",columns:{y:{title:"Values for y-axis"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},x_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"x_axis_tick"},{label:"Auto",value:"auto",hide:"x_axis_tick"},{label:"Float",value:"f",show:"x_axis_tick"},{label:"Exponent",value:"e",show:"x_axis_tick"},{label:"Integer",value:"d",hide:"x_axis_tick"},{label:"Percentage",value:"p",show:"x_axis_tick"},{label:"Rounded",value:"r",show:"x_axis_tick"},{label:"SI-prefix",value:"s",show:"x_axis_tick"}]},x_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"},y_axis_type:{title:"Axis value type",info:"Select the value type of the axis.",type:"select",init:"auto",data:[{label:"-- Do not show values --",value:"hide",hide:"y_axis_tick"},{label:"Auto",value:"auto",hide:"y_axis_tick"},{label:"Float",value:"f",show:"y_axis_tick"},{label:"Exponent",value:"e",show:"y_axis_tick"},{label:"Integer",value:"d",hide:"y_axis_tick"},{label:"Percentage",value:"p",show:"y_axis_tick"},{label:"Rounded",value:"r",show:"y_axis_tick"},{label:"SI-prefix",value:"s",show:"y_axis_tick"}]},y_axis_tick:{title:"Axis tick format",info:"Select the tick format for the axis.",type:"select",init:".1",data:[{label:"0.00001",value:".5"},{label:"0.0001",value:".4"},{label:"0.001",value:".3"},{label:"0.01",value:".2"},{label:"0.1",value:".1"},{label:"1",value:"1"}]},separator_legend:{title:"Others",type:"separator"},show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"true",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_bardiagram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram"})}),define("plugin/charts/nvd3_histogram/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Histogram",execute:"histogram",columns:{y:{title:"Observations"}},settings:{x_axis_label:{init:"Breaks"},y_axis_label:{init:"Density"},y_axis_type:{init:"f"},y_axis_tick:{init:".2"}}})}),define("plugin/charts/nvd3_horizontal/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Bar diagram (horizontal)",settings:{x_axis_type:{init:"hide"}}})}),define("plugin/charts/nvd3_line/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line chart"})}),define("plugin/charts/nvd3_linewithfocus/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Line with focus"})}),define("plugin/charts/nvd3_piechart/config",[],function(){return{title:"Pie chart",library:"nvd3.js",tag:"svg",use_panels:!0,columns:{label:{title:"Labels",is_label:!0},y:{title:"Values"}},settings:{show_legend:{title:"Show legend",info:"Would you like to add a legend?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]},donut_ratio:{title:"Donut ratio",info:"Determine how large the donut hole will be.",type:"select",init:"0.5",data:[{label:"50%",value:"0.5"},{label:"25%",value:"0.25"},{label:"10%",value:"0.10"},{label:"0%",value:"0"}]},label_separator:{type:"separator",title:"Label settings"},label_type:{title:"Donut label",info:"What would you like to show for each slice?",type:"select",init:"percent",data:[{label:"-- Nothing --",value:"hide",hide:"label_outside"},{label:"Label column",value:"key",show:"label_outside"},{label:"Value column",value:"value",show:"label_outside"},{label:"Percentage",value:"percent",show:"label_outside"}]},label_outside:{title:"Show outside",info:"Would you like to show labels outside the donut?",type:"select",init:"false",data:[{label:"Yes",value:"true"},{label:"No",value:"false"}]}}}}),define("plugin/charts/nvd3_scatterplot/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Scatter plot",columns:{x:{title:"Values for x-axis"}}})}),define("plugin/charts/nvd3_stackedarea/config",["plugin/charts/nvd3/config"],function(e){return $.extend(!0,{},e,{title:"Stacked area"})}),define("plugin/charts/highcharts_boxplot/config",[],function(){return{title:"Box plot",library:"highcharts.js",element:"div",execute:"boxplot",columns:{y:{title:"Observations"}},settings:{separator_label:{title:"X axis",type:"separator"},x_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"X-axis",placeholder:"Axis label"},separator_tick:{title:"Y axis",type:"separator"},y_axis_label:{title:"Axis label",info:"Provide a label for the axis.",type:"text",init:"Y-axis",placeholder:"Axis label"}}}}),define("plugin/charts/types",["plugin/charts/nvd3_bardiagram/config","plugin/charts/nvd3_histogram/config","plugin/charts/nvd3_horizontal/config","plugin/charts/nvd3_line/config","plugin/charts/nvd3_linewithfocus/config","plugin/charts/nvd3_piechart/config","plugin/charts/nvd3_scatterplot/config","plugin/charts/nvd3_stackedarea/config","plugin/charts/highcharts_boxplot/config"],function(e,t,n,r,i,s,o,u,a){return Backbone.Model.extend({defaults:{nvd3_bardiagram:e,nvd3_horizontal:n,nvd3_histogram:t,nvd3_line:r,nvd3_linewithfocus:i,nvd3_piechart:s,nvd3_scatterplot:o,nvd3_stackedarea:u,highcharts_boxplot:a}})}),define("plugin/app",["mvc/ui/ui-modal","mvc/ui/ui-portlet","plugin/library/ui","utils/utils","plugin/library/jobs","plugin/library/datasets","plugin/library/storage","plugin/views/viewer","plugin/views/editor","plugin/models/config","plugin/models/chart","plugin/charts/types"],function(e,t,n,r,i,s,o,u,a,f,l,c){return Backbone.View.extend({initialize:function(t){this.options=t,Galaxy&&Galaxy.modal?this.modal=Galaxy.modal:this.modal=new e.View,this.config=new f,this.types=new c,this.chart=new l,this.jobs=new i(this),this.datasets=new s(this),this.storage=new o(this),this.viewer_view=new u(this),this.editor_view=new a(this),this.$el.append(this.viewer_view.$el),this.$el.append(this.editor_view.$el);if(!this.storage.load())this.go("editor");else{this.go("viewer");var n=this;this.chart.deferred.execute(function(){n.chart.trigger("redraw")})}},go:function(e){$(".tooltip").hide();switch(e){case"editor":this.editor_view.show(),this.viewer_view.hide();break;case"viewer":this.editor_view.hide(),this.viewer_view.show()}},execute:function(e){},onunload:function(){},log:function(e,t){console.log(e+" "+t)}})});
\ No newline at end of file
diff -r 82605b688d874c0472fd299dbf0485eff10c397f -r 4b430f408ac762a6f2a6856fb199a347bc693fbb config/plugins/visualizations/charts/static/views/group.js
--- a/config/plugins/visualizations/charts/static/views/group.js
+++ b/config/plugins/visualizations/charts/static/views/group.js
@@ -144,7 +144,7 @@
}
// loading
- self.chart.state('wait', 'Metadata initialized...');
+ self.chart.state('ok', 'Metadata initialized...');
// unregister
self.chart.deferred.done(process_id);
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: Improve visualization registry warning info when datatype class not found by lookup
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/82605b688d87/
Changeset: 82605b688d87
User: carlfeberhard
Date: 2014-04-19 00:04:13
Summary: Improve visualization registry warning info when datatype class not found by lookup
Affected #: 1 file
diff -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 -r 82605b688d874c0472fd299dbf0485eff10c397f lib/galaxy/visualization/registry.py
--- a/lib/galaxy/visualization/registry.py
+++ b/lib/galaxy/visualization/registry.py
@@ -240,10 +240,13 @@
# parse test_result based on result_type (curr: only datatype has to do this)
if result_type == 'datatype':
# convert datatypes to their actual classes (for use with isinstance)
- test_result = trans.app.datatypes_registry.get_datatype_class_by_name( test_result )
+ datatype_class_name = test_result
+ test_result = trans.app.datatypes_registry.get_datatype_class_by_name( datatype_class_name )
if not test_result:
# warn if can't find class, but continue (with other tests)
- log.warn( 'visualizations_registry cannot find class (%s) for applicability test', test_result )
+ log.warn( 'visualizations_registry cannot find class (%s)' +
+ ' for applicability test on: %s, id: %s', datatype_class_name,
+ target_object, getattr( target_object, 'id', '' ) )
continue
#NOTE: tests are OR'd, if any test passes - the visualization can be applied
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: martenson: data libraries: small API changes; bugfix; deferred queue for adding datasets from history to library; permission handling work
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/6de936f80658/
Changeset: 6de936f80658
User: martenson
Date: 2014-04-18 23:16:58
Summary: data libraries: small API changes; bugfix; deferred queue for adding datasets from history to library; permission handling work
Affected #: 10 files
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 lib/galaxy/webapps/galaxy/api/folder_contents.py
--- a/lib/galaxy/webapps/galaxy/api/folder_contents.py
+++ b/lib/galaxy/webapps/galaxy/api/folder_contents.py
@@ -86,16 +86,16 @@
full_path = build_path( folder )[::-1]
folder_contents = []
- time_updated = ''
- time_created = ''
+ update_time = ''
+ create_time = ''
# Go through every accessible item in the folder and include its meta-data.
for content_item in self._load_folder_contents( trans, folder ):
can_access = trans.app.security_agent.can_access_library_item( current_user_roles, content_item, trans.user )
if ( can_access or ( content_item.api_type == 'folder' and trans.app.security_agent.folder_is_unrestricted( content_item ) ) ):
return_item = {}
encoded_id = trans.security.encode_id( content_item.id )
- time_updated = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
- time_created = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
+ update_time = content_item.update_time.strftime( "%Y-%m-%d %I:%M %p" )
+ create_time = content_item.create_time.strftime( "%Y-%m-%d %I:%M %p" )
# For folder return also hierarchy values
if content_item.api_type == 'folder':
@@ -118,8 +118,8 @@
return_item.update( dict( id = encoded_id,
type = content_item.api_type,
name = content_item.name,
- time_updated = time_updated,
- time_created = time_created
+ update_time = update_time,
+ create_time = create_time
) )
folder_contents.append( return_item )
@@ -178,11 +178,14 @@
raise exceptions.InsufficientPermissionsException( 'You do not have proper permissions to add a dataset to a folder with id (%s)' % ( encoded_folder_id ) )
ldda = self.copy_hda_to_library_folder( trans, hda, folder, ldda_message=ldda_message )
+ update_time = ldda.update_time.strftime( "%Y-%m-%d %I:%M %p" )
ldda_dict = ldda.to_dict()
rval = trans.security.encode_dict_ids( ldda_dict )
+ rval['update_time'] = update_time
except Exception, exc:
- if 'not accessible to the current user' in str( exc ):
+ # TODO handle exceptions better within the mixins
+ if ( ( 'not accessible to the current user' in str( exc ) ) or ( 'You are not allowed to access this dataset' in str( exc ) ) ):
raise exceptions.ItemAccessibilityException( 'You do not have access to the requested item' )
else:
log.exception( exc )
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 lib/galaxy/webapps/galaxy/api/lda_datasets.py
--- a/lib/galaxy/webapps/galaxy/api/lda_datasets.py
+++ b/lib/galaxy/webapps/galaxy/api/lda_datasets.py
@@ -13,6 +13,7 @@
import urllib2
import zipfile
from galaxy import exceptions
+from galaxy.exceptions import ItemAccessibilityException, MessageException, ItemDeletionException, ObjectNotFound
from galaxy.web import _future_expose_api as expose_api
from galaxy.web import _future_expose_api_anonymous as expose_api_anonymous
from galaxy import util
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/galaxy.library.js
--- a/static/scripts/galaxy.library.js
+++ b/static/scripts/galaxy.library.js
@@ -30,7 +30,6 @@
var LibraryRouter = Backbone.Router.extend({
routes: {
"" : "libraries",
- "sort/:sort_by/:order" : "sort_libraries",
"folders/:id" : "folder_content",
"folders/:folder_id/download/:format" : "download"
}
@@ -72,11 +71,6 @@
// TODO place caching here, sessionstorage/localstorage?
if (Galaxy.libraries.folderToolbarView){
Galaxy.libraries.folderToolbarView.$el.unbind('click');
- // Galaxy.libraries.folderToolbarView.remove();
- }
- if (Galaxy.libraries.folderListView){
- // Galaxy.libraries.folderListView.$el.unbind('click');
- // Galaxy.libraries.folderListView.remove();
}
Galaxy.libraries.folderToolbarView = new mod_foldertoolbar_view.FolderToolbarView({id: id});
Galaxy.libraries.folderListView = new mod_folderlist_view.FolderListView({id: id});
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/mvc/library/library-folderlist-view.js
--- a/static/scripts/mvc/library/library-folderlist-view.js
+++ b/static/scripts/mvc/library/library-folderlist-view.js
@@ -116,12 +116,12 @@
},
addOne: function(model){
- if (model.get('type') === 'file'){
+ if (model.get('data_type') !== 'folder'){
this.options.contains_file = true;
model.set('readable_size', this.size_to_string(model.get('file_size')));
}
var rowView = new mod_library_folderrow_view.FolderRowView(model);
- this.$el.find('#folder_list_body').prepend(rowView.el);
+ this.$el.find('#first_folder_item').after(rowView.el);
},
sort_clicked : function(event){
@@ -256,14 +256,14 @@
tmpl_array.push(' <th>time updated (UTC)</th>');
tmpl_array.push(' </thead>');
tmpl_array.push(' <tbody id="folder_list_body">');
- // tmpl_array.push(' <tr>');
- // tmpl_array.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');
- // tmpl_array.push(' <td></td>');
- // tmpl_array.push(' <td></td>');
- // tmpl_array.push(' <td></td>');
- // tmpl_array.push(' <td></td>');
- // tmpl_array.push(' <td></td>');
- // tmpl_array.push(' </tr>');
+ tmpl_array.push(' <tr id="first_folder_item">');
+ tmpl_array.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');
+ tmpl_array.push(' <td></td>');
+ tmpl_array.push(' <td></td>');
+ tmpl_array.push(' <td></td>');
+ tmpl_array.push(' <td></td>');
+ tmpl_array.push(' <td></td>');
+ tmpl_array.push(' </tr>');
tmpl_array.push(' </tbody>');
tmpl_array.push('</table>');
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/mvc/library/library-folderrow-view.js
--- a/static/scripts/mvc/library/library-folderrow-view.js
+++ b/static/scripts/mvc/library/library-folderrow-view.js
@@ -206,7 +206,7 @@
tmpl_array.push(' <td></td>');
// print item count only if it is given
// tmpl_array.push(' <td><% if (typeof content_item.get("item_count") !== "undefined") { _.escape(content_item.get("item_count")); print("item(s)") } %></td>');
- tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>'); // time updated
+ tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push('</tr>');
return _.template(tmpl_array.join(''));
@@ -223,7 +223,7 @@
tmpl_array.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>'); // dataset
tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>'); // data type
tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>'); // size
- tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>'); // time updated
+ tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>'); // time updated
tmpl_array.push('</tr>');
return _.template(tmpl_array.join(''));
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/mvc/library/library-foldertoolbar-view.js
@@ -152,10 +152,12 @@
// import all selected datasets into history
importAllIntoHistory : function (){
- //disable the button to prevent multiple submission
+ // disable the button to prevent multiple submission
this.modal.disableButton('Import');
var history_id = $("select[name=dataset_import_bulk] option:selected").val();
+ // we can save last used history to pre-select it next time
+ this.options.last_used_history_id = history_id;
var history_name = $("select[name=dataset_import_bulk] option:selected").text();
var dataset_ids = [];
@@ -174,29 +176,35 @@
// prepare the dataset objects to be imported
var datasets_to_import = [];
for (var i = dataset_ids.length - 1; i >= 0; i--) {
- library_dataset_id = dataset_ids[i];
+ var library_dataset_id = dataset_ids[i];
var historyItem = new mod_library_model.HistoryItem();
- var self = this;
historyItem.url = historyItem.urlRoot + history_id + '/contents';
historyItem.content = library_dataset_id;
historyItem.source = 'library';
datasets_to_import.push(historyItem);
}
// call the recursive function to call ajax one after each other (request FIFO queue)
- this.chainCall(datasets_to_import);
+ this.chainCall(datasets_to_import, history_name);
},
- chainCall: function(history_item_set){
+ chainCall: function(history_item_set, history_name){
var self = this;
var popped_item = history_item_set.pop();
if (typeof popped_item === "undefined") {
- mod_toastr.success('All datasets imported');
+ mod_toastr.success('Datasets were imported to history: ' + history_name);
this.modal.hide();
return;
}
- var promise = $.when(popped_item.save({content: popped_item.content, source: popped_item.source})).done(function(a1){
- self.updateProgress();
- self.chainCall(history_item_set);
+ var promise = $.when(popped_item.save({content: popped_item.content, source: popped_item.source}));
+
+ promise.done(function(a1){
+ self.updateProgress();
+ self.chainCall(history_item_set, history_name);
+ })
+ .fail(function(a1){
+ mod_toastr.error('An error occured :(');
+ self.updateProgress();
+ self.chainCall(history_item_set, history_name);
});
},
@@ -231,7 +239,7 @@
//url and data options required
if( url && data ){
//data can be string of parameters or array/object
- data = typeof data == 'string' ? data : $.param(data);
+ data = typeof data === 'string' ? data : $.param(data);
//split params into form inputs
var inputs = '';
$.each(data.split('&'), function(){
@@ -267,7 +275,7 @@
self.fetchAndDisplayHistoryContents(event.target.value);
});
} else {
- mod_toastr.error('Unable to retrieve histories. Please report this error.');
+ mod_toastr.error('An error ocurred :(');
}
});
},
@@ -278,12 +286,11 @@
history_contents.fetch({
success: function(history_contents){
var history_contents_template = self.templateHistoryContents();
- mod_toastr.success('history contents fetched');
self.histories.get(history_id).set({'contents' : history_contents});
self.modal.$el.find('#selected_history_content').html(history_contents_template({history_contents: history_contents.models.reverse()}));
},
error: function(){
- mod_toastr.error('history contents fetch failed');
+ mod_toastr.error('An error ocurred :(');
}
});
},
@@ -313,7 +320,6 @@
for (var i = history_dataset_ids.length - 1; i >= 0; i--) {
history_dataset_id = history_dataset_ids[i];
var folder_item = new mod_library_model.Item();
- var self = this;
folder_item.url = '/api/folders/' + this.options.id + '/contents';
folder_item.set({'from_hda_id':history_dataset_id});
hdas_to_add.push(folder_item);
@@ -327,15 +333,28 @@
this.added_hdas = new mod_library_model.Folder();
var popped_item = hdas_set.pop();
if (typeof popped_item === "undefined") {
- mod_toastr.success('Selected datasets from history imported');
+ mod_toastr.success('Datasets from history added to the folder');
this.modal.hide();
return this.added_hdas;
}
- var promise = $.when(popped_item.save({from_hda_id: popped_item.get('from_hda_id')})).done(function(a1){
- Galaxy.libraries.folderListView.collection.add(a1);
- self.updateProgress();
- self.chainCallAddingHdas(hdas_set);
- });
+ var promise = $.when(popped_item.save({from_hda_id: popped_item.get('from_hda_id')}));
+
+ promise.done(function(a1){
+ // we are fine
+ Galaxy.libraries.folderListView.collection.add(a1);
+ self.updateProgress();
+ self.chainCallAddingHdas(hdas_set);
+ })
+ .fail(function(data){
+ // we have a problem
+ if (data.status===403){
+ mod_toastr.error('You are not allowed to access a dataset');
+ } else {
+ mod_toastr.error('An error occured :(');
+ }
+ self.updateProgress();
+ self.chainCallAddingHdas(hdas_set);
+ });
},
templateToolBar: function(){
@@ -346,10 +365,12 @@
tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');
// TOOLBAR
tmpl_array.push('<div id="library_folder_toolbar" >');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="toolbtn_add_files primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');
- tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');
- tmpl_array.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display:none; ">');
+ tmpl_array.push('<div class="btn-group">');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');
+ tmpl_array.push('</div>');
+ tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" style="margin-left: 0.5em; " type="button"><span class="fa fa-book"></span> to history</button>');
+ tmpl_array.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; ">');
tmpl_array.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');
tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');
tmpl_array.push(' </button>');
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/packed/galaxy.library.js
--- a/static/scripts/packed/galaxy.library.js
+++ b/static/scripts/packed/galaxy.library.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({routes:{"":"libraries","sort/:sort_by/:order":"sort_libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}if(Galaxy.libraries.folderListView){}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:m});Galaxy.libraries.folderListView=new a.FolderListView({id:m})});this.library_router.on("route:download",function(m,n){if($("#center").find(":checked").length===0){g.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(m,n);Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/base-mvc","mvc/library/library-model","mvc/library/library-folderlist-view","mvc/library/library-librarylist-view","mvc/library/library-librarytoolbar-view","mvc/library/library-foldertoolbar-view"],function(e,c,g,k,h,a,f,d,i){var l=Backbone.Router.extend({routes:{"":"libraries","folders/:id":"folder_content","folders/:folder_id/download/:format":"download"}});var j=k.SessionStorageModel.extend({defaults:{with_deleted:false,sort_order:"asc",sort_by:"name"}});var b=Backbone.View.extend({libraryToolbarView:null,libraryListView:null,library_router:null,folderToolbarView:null,folderListView:null,initialize:function(){Galaxy.libraries=this;this.preferences=new j({id:"global-lib-prefs"});this.library_router=new l();this.library_router.on("route:libraries",function(){Galaxy.libraries.libraryToolbarView=new d.LibraryToolbarView();Galaxy.libraries.libraryListView=new f.LibraryListView()});this.library_router.on("route:folder_content",function(m){if(Galaxy.libraries.folderToolbarView){Galaxy.libraries.folderToolbarView.$el.unbind("click")}Galaxy.libraries.folderToolbarView=new i.FolderToolbarView({id:m});Galaxy.libraries.folderListView=new a.FolderListView({id:m})});this.library_router.on("route:download",function(m,n){if($("#center").find(":checked").length===0){g.info("You have to select some datasets to download");Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:true,replace:true})}else{Galaxy.libraries.folderToolbarView.download(m,n);Galaxy.libraries.library_router.navigate("folders/"+m,{trigger:false,replace:true})}});Backbone.history.start({pushState:false})}});return{GalaxyApp:b}});
\ No newline at end of file
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/packed/mvc/library/library-folderlist-view.js
--- a/static/scripts/packed/mvc/library/library-folderlist-view.js
+++ b/static/scripts/packed/mvc/library/library-folderlist-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},initialize:function(g){var h=this;this.options=_.defaults(this.options||{},g);this.queue=jQuery.Deferred();this.queue.resolve();this.collection=new d.Folder();this.listenTo(this.collection,"add",this.addOne);this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";this.folderContainer.fetch({success:function(i){h.render();var j=i.get("folder").models;h.addAll(j)},error:function(){f.error("An error occured :(")}})},render:function(g){this.options=_.defaults(this.options||{},g);var h=this.templateFolder();var i=false;var j=this.folderContainer.attributes.metadata.full_path;var k;if(j.length===1){k=0}else{k=j[j.length-2][0]}this.$el.html(h({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:k,order:this.sort}));if(this.collection.models.length>0){this.renderRows()}var g=this.folderContainer.attributes.metadata;g.contains_file=this.options.contains_file;Galaxy.libraries.folderToolbarView.configureElements(g);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(){for(var j=0;j<this.collection.models.length;j++){var h=this.collection.models[j];var g=new a.FolderRowView(h);this.$el.find("#folder_list_body").append(g.el)}},addAll:function(g){_.each(g.reverse(),function(h){Galaxy.libraries.folderListView.collection.add(h)})},addOne:function(h){if(h.get("type")==="file"){this.options.contains_file=true;h.set("readable_size",this.size_to_string(h.get("file_size")))}var g=new a.FolderRowView(h);this.$el.find("#folder_list_body").prepend(g.el)},sort_clicked:function(g){g.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render()},sortFolder:function(h,g){if(h==="name"){if(g==="asc"){this.collection.sortByNameAsc()}else{if(g==="desc"){this.collection.sortByNameDesc()}}}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);(g)?that.makeDarkRow($row):that.makeWhiteRow($row)})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light");g.find("a").removeClass("light");g.addClass("dark");g.find("a").addClass("dark");g.find("span").removeClass("fa-file-o");g.find("span").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark");g.find("a").removeClass("dark");g.addClass("light");g.find("a").addClass("light");g.find("span").addClass("fa-file-o");g.find("span").removeClass("fa-file")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(' <th><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');g.push(" <th>data type</th>");g.push(" <th>size</th>");g.push(" <th>time updated (UTC)</th>");g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(" </tbody>");g.push("</table>");return _.template(g.join(""))}});return{FolderListView:b}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model","mvc/library/library-folderrow-view"],function(c,e,f,d,a){var b=Backbone.View.extend({el:"#folder_items_element",progress:0,progressStep:1,modal:null,folderContainer:null,sort:"asc",events:{"click #select-all-checkboxes":"selectAll","click .dataset_row":"selectClickedRow","click .sort-folder-link":"sort_clicked"},initialize:function(g){var h=this;this.options=_.defaults(this.options||{},g);this.queue=jQuery.Deferred();this.queue.resolve();this.collection=new d.Folder();this.listenTo(this.collection,"add",this.addOne);this.folderContainer=new d.FolderContainer({id:this.options.id});this.folderContainer.url=this.folderContainer.attributes.urlRoot+this.options.id+"/contents";this.folderContainer.fetch({success:function(i){h.render();var j=i.get("folder").models;h.addAll(j)},error:function(){f.error("An error occured :(")}})},render:function(g){this.options=_.defaults(this.options||{},g);var h=this.templateFolder();var i=false;var j=this.folderContainer.attributes.metadata.full_path;var k;if(j.length===1){k=0}else{k=j[j.length-2][0]}this.$el.html(h({path:this.folderContainer.attributes.metadata.full_path,id:this.options.id,upper_folder_id:k,order:this.sort}));if(this.collection.models.length>0){this.renderRows()}var g=this.folderContainer.attributes.metadata;g.contains_file=this.options.contains_file;Galaxy.libraries.folderToolbarView.configureElements(g);$("#center [data-toggle]").tooltip();$("#center").css("overflow","auto")},renderRows:function(){for(var j=0;j<this.collection.models.length;j++){var h=this.collection.models[j];var g=new a.FolderRowView(h);this.$el.find("#folder_list_body").append(g.el)}},addAll:function(g){_.each(g.reverse(),function(h){Galaxy.libraries.folderListView.collection.add(h)})},addOne:function(h){if(h.get("data_type")!=="folder"){this.options.contains_file=true;h.set("readable_size",this.size_to_string(h.get("file_size")))}var g=new a.FolderRowView(h);this.$el.find("#first_folder_item").after(g.el)},sort_clicked:function(g){g.preventDefault();if(this.sort==="asc"){this.sortFolder("name","desc");this.sort="desc"}else{this.sortFolder("name","asc");this.sort="asc"}this.render()},sortFolder:function(h,g){if(h==="name"){if(g==="asc"){this.collection.sortByNameAsc()}else{if(g==="desc"){this.collection.sortByNameDesc()}}}},size_to_string:function(g){var h="";if(g>=100000000000){g=g/100000000000;h="TB"}else{if(g>=100000000){g=g/100000000;h="GB"}else{if(g>=100000){g=g/100000;h="MB"}else{if(g>=100){g=g/100;h="KB"}else{g=g*10;h="b"}}}}return(Math.round(g)/10)+h},selectAll:function(h){var g=h.target.checked;that=this;$(":checkbox").each(function(){this.checked=g;$row=$(this.parentElement.parentElement);(g)?that.makeDarkRow($row):that.makeWhiteRow($row)})},selectClickedRow:function(h){var j="";var g;var i;if(h.target.localName==="input"){j=h.target;g=$(h.target.parentElement.parentElement);i="input"}else{if(h.target.localName==="td"){j=$("#"+h.target.parentElement.id).find(":checkbox")[0];g=$(h.target.parentElement);i="td"}}if(j.checked){if(i==="td"){j.checked="";this.makeWhiteRow(g)}else{if(i==="input"){this.makeDarkRow(g)}}}else{if(i==="td"){j.checked="selected";this.makeDarkRow(g)}else{if(i==="input"){this.makeWhiteRow(g)}}}},makeDarkRow:function(g){g.removeClass("light");g.find("a").removeClass("light");g.addClass("dark");g.find("a").addClass("dark");g.find("span").removeClass("fa-file-o");g.find("span").addClass("fa-file")},makeWhiteRow:function(g){g.removeClass("dark");g.find("a").removeClass("dark");g.addClass("light");g.find("a").addClass("light");g.find("span").addClass("fa-file-o");g.find("span").removeClass("fa-file")},templateFolder:function(){var g=[];g.push('<ol class="breadcrumb">');g.push(' <li><a title="Return to the list of libraries" href="#">Libraries</a></li>');g.push(" <% _.each(path, function(path_item) { %>");g.push(" <% if (path_item[0] != id) { %>");g.push(' <li><a title="Return to this folder" href="#/folders/<%- path_item[0] %>"><%- path_item[1] %></a></li> ');g.push("<% } else { %>");g.push(' <li class="active"><span title="You are in this folder"><%- path_item[1] %></span></li>');g.push(" <% } %>");g.push(" <% }); %>");g.push("</ol>");g.push('<table id="folder_table" class="grid table table-condensed">');g.push(" <thead>");g.push(' <th class="button_heading"></th>');g.push(' <th style="text-align: center; width: 20px; "><input id="select-all-checkboxes" style="margin: 0;" type="checkbox"></th>');g.push(' <th><a class="sort-folder-link" title="Click to reverse order" href="#">name</a><span title="Sorted alphabetically" class="fa fa-sort-alpha-<%- order %>"></span></th>');g.push(" <th>data type</th>");g.push(" <th>size</th>");g.push(" <th>time updated (UTC)</th>");g.push(" </thead>");g.push(' <tbody id="folder_list_body">');g.push(' <tr id="first_folder_item">');g.push(' <td><a href="#<% if (upper_folder_id !== 0){ print("folders/" + upper_folder_id)} %>" title="Go to parent folder" class="btn_open_folder btn btn-default btn-xs">..<a></td>');g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" <td></td>");g.push(" </tr>");g.push(" </tbody>");g.push("</table>");return _.template(g.join(""))}});return{FolderListView:b}});
\ No newline at end of file
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/packed/mvc/library/library-folderrow-view.js
--- a/static/scripts/packed/mvc/library/library-folderrow-view.js
+++ b/static/scripts/packed/mvc/library/library-folderrow-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .library-dataset":"showDatasetDetails"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";g=this.templateRowFile()}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(i){i.preventDefault();var j=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=j;var f=this;h.fetch({success:function(k){g.fetch({success:function(l){f.renderModalAfterFetch(k,l)},error:function(){e.error("An error occured during fetching histories:(");f.renderModalAfterFetch(k)}})},error:function(){e.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(){e.error("An error occured! Dataset not imported. Please try again.");g.modal.enableButton("Import");g.modal.enableButton("Download")}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("time_updated")) %></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({lastSelectedHistory:"",events:{"click .library-dataset":"showDatasetDetails"},options:{type:null},initialize:function(f){this.render(f)},render:function(f){var g=null;if(f.get("type")==="folder"){this.options.type="folder";g=this.templateRowFolder()}else{this.options.type="file";g=this.templateRowFile()}this.setElement(g({content_item:f}));this.$el.show();return this},showDatasetDetails:function(i){i.preventDefault();var j=this.id;var h=new c.Item();var g=new c.GalaxyHistories();h.id=j;var f=this;h.fetch({success:function(k){g.fetch({success:function(l){f.renderModalAfterFetch(k,l)},error:function(){e.error("An error occured during fetching histories:(");f.renderModalAfterFetch(k)}})},error:function(){e.error("An error occured during loading dataset details :(")}})},renderModalAfterFetch:function(k,h){var i=this.size_to_string(k.get("file_size"));var j=_.template(this.templateDatasetModal(),{item:k,size:i});var g=this;this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Dataset Details",body:j,buttons:{Import:function(){g.importCurrentIntoHistory()},Download:function(){g.downloadCurrent()},Close:function(){g.modal.hide()}}});$(".peek").html(k.get("peek"));if(typeof history.models!==undefined){var f=_.template(this.templateHistorySelectInModal(),{histories:h.models});$(this.modal.elMain).find(".buttons").prepend(f);if(g.lastSelectedHistory.length>0){$(this.modal.elMain).find("#dataset_import_single").val(g.lastSelectedHistory)}}},size_to_string:function(f){var g="";if(f>=100000000000){f=f/100000000000;g="TB"}else{if(f>=100000000){f=f/100000000;g="GB"}else{if(f>=100000){f=f/100000;g="MB"}else{if(f>=100){f=f/100;g="KB"}else{f=f*10;g="b"}}}}return(Math.round(f)/10)+g},downloadCurrent:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var f=[];f.push($("#id_row").attr("data-id"));var g="/api/libraries/datasets/download/uncompressed";var h={ldda_ids:f};this.processDownload(g,h);this.modal.enableButton("Import");this.modal.enableButton("Download")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},importCurrentIntoHistory:function(){this.modal.disableButton("Import");this.modal.disableButton("Download");var h=$(this.modal.elMain).find("select[name=dataset_import_single] option:selected").val();this.lastSelectedHistory=h;var f=$("#id_row").attr("data-id");var i=new c.HistoryItem();var g=this;i.url=i.urlRoot+h+"/contents";i.save({content:f,source:"library"},{success:function(){e.success("Dataset imported");g.modal.enableButton("Import");g.modal.enableButton("Download")},error:function(){e.error("An error occured! Dataset not imported. Please try again.");g.modal.enableButton("Import");g.modal.enableButton("Download")}})},templateRowFolder:function(){tmpl_array=[];tmpl_array.push('<tr class="folder_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Folder" class="fa fa-folder-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(" <td></td>");tmpl_array.push(" <td>");tmpl_array.push(' <a href="#folders/<%- content_item.id %>"><%- content_item.get("name") %></a>');tmpl_array.push(' <% if (content_item.get("item_count") === 0) { %>');tmpl_array.push(" <span>(empty folder)</span>");tmpl_array.push(" <% } %>");tmpl_array.push(" </td>");tmpl_array.push(" <td>folder</td>");tmpl_array.push(" <td></td>");tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateRowFile:function(){tmpl_array=[];tmpl_array.push('<tr class="dataset_row light" id="<%- content_item.id %>">');tmpl_array.push(" <td>");tmpl_array.push(' <span title="Dataset" class="fa fa-file-o"></span>');tmpl_array.push(" </td>");tmpl_array.push(' <td style="text-align: center; "><input style="margin: 0;" type="checkbox"></td>');tmpl_array.push(' <td><a href="#" class="library-dataset"><%- content_item.get("name") %><a></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("data_type")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("readable_size")) %></td>');tmpl_array.push(' <td><%= _.escape(content_item.get("update_time")) %></td>');tmpl_array.push("</tr>");return _.template(tmpl_array.join(""))},templateDatasetModal:function(){var f=[];f.push('<div class="modal_table">');f.push(' <table class="grid table table-striped table-condensed">');f.push(" <tr>");f.push(' <th scope="row" id="id_row" data-id="<%= _.escape(item.get("ldda_id")) %>">Name</th>');f.push(' <td><%= _.escape(item.get("name")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Data type</th>');f.push(' <td><%= _.escape(item.get("data_type")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Genome build</th>');f.push(' <td><%= _.escape(item.get("genome_build")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Size</th>');f.push(" <td><%= _.escape(size) %></td>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Date uploaded (UTC)</th>');f.push(' <td><%= _.escape(item.get("date_uploaded")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Uploaded by</th>');f.push(' <td><%= _.escape(item.get("uploaded_by")) %></td>');f.push(" </tr>");f.push(' <tr scope="row">');f.push(' <th scope="row">Data Lines</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_data_lines")) %></td>');f.push(" </tr>");f.push(' <th scope="row">Comment Lines</th>');f.push(' <% if (item.get("metadata_comment_lines") === "") { %>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_comment_lines")) %></td>');f.push(" <% } else { %>");f.push(' <td scope="row">unknown</td>');f.push(" <% } %>");f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Number of Columns</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_columns")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Column Types</th>');f.push(' <td scope="row"><%= _.escape(item.get("metadata_column_types")) %></td>');f.push(" </tr>");f.push(" <tr>");f.push(' <th scope="row">Miscellaneous information</th>');f.push(' <td scope="row"><%= _.escape(item.get("misc_blurb")) %></td>');f.push(" </tr>");f.push(" </table>");f.push(' <pre class="peek">');f.push(" </pre>");f.push("</div>");return f.join("")},templateHistorySelectInModal:function(){var f=[];f.push('<span id="history_modal_combo" style="width:100%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_single" name="dataset_import_single" style="width:40%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return f.join("")}});return{FolderRowView:a}});
\ No newline at end of file
diff -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 -r 6de936f80658bbfaf0140f262628afd5e03ce0d7 static/scripts/packed/mvc/library/library-foldertoolbar-view.js
--- a/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
+++ b/static/scripts/packed/mvc/library/library-foldertoolbar-view.js
@@ -1,1 +1,1 @@
-define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal"},defaults:{can_add_library_item:false,contains_file:false},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(f){this.options=_.extend(this.options,f);var h=this.templateToolBar();var g=false;if(Galaxy.currUser){g=Galaxy.currUser.isAdmin()}this.$el.html(h({id:this.options.id,admin_user:g}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$("#toolbtn_create_folder").show();$(".toolbtn_add_files").show()}if(this.options.contains_file===true){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var h=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];h.url=h.urlRoot+"/"+current_folder_id;var g=this;h.save(f,{success:function(i){g.modal.hide();e.success("Folder created");i.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(i)},error:function(){e.error("An error occured :(")}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(){}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var h=$("select[name=dataset_import_bulk] option:selected").val();var m=$("select[name=dataset_import_bulk] option:selected").text();var o=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){o.push(this.parentElement.parentElement.id)}});var n=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(n({history_name:m}));var j=100/o.length;this.initProgress(j);var f=[];for(var g=o.length-1;g>=0;g--){library_dataset_id=o[g];var k=new c.HistoryItem();var l=this;k.url=k.urlRoot+h+"/contents";k.content=library_dataset_id;k.source="library";f.push(k)}this.chainCall(f)},chainCall:function(g){var f=this;var h=g.pop();if(typeof h==="undefined"){e.success("All datasets imported");this.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source})).done(function(j){f.updateProgress();f.chainCall(g)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h=="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("Unable to retrieve histories. Please report this error.")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();e.success("history contents fetched");f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("history contents fetch failed")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var m=this.options.folder_name;var l=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(l({folder_name:m}));this.progressStep=100/f.length;this.progress=0;var k=[];for(var j=f.length-1;j>=0;j--){history_dataset_id=f[j];var h=new c.Item();var g=this;h.url="/api/folders/"+this.options.id+"/contents";h.set({from_hda_id:history_dataset_id});k.push(h)}this.chainCallAddingHdas(k)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){e.success("Selected datasets from history imported");this.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")})).done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<div id="library_folder_toolbar" >');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="toolbtn_add_files primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" style="margin-left: 0.5em; display:none;" type="button"><span class="fa fa-book"></span> to history</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; display:none; ">');tmpl_array.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView:a}});
\ No newline at end of file
+define(["galaxy.masthead","utils/utils","libs/toastr","mvc/library/library-model"],function(b,d,e,c){var a=Backbone.View.extend({el:"#center",events:{"click #toolbtn_create_folder":"createFolderFromModal","click #toolbtn_bulk_import":"modalBulkImport","click .toolbtn_add_files":"addFilesToFolderModal"},defaults:{can_add_library_item:false,contains_file:false},modal:null,histories:null,initialize:function(f){this.options=_.defaults(f||{},this.defaults);this.render()},render:function(f){this.options=_.extend(this.options,f);var h=this.templateToolBar();var g=false;if(Galaxy.currUser){g=Galaxy.currUser.isAdmin()}this.$el.html(h({id:this.options.id,admin_user:g}))},configureElements:function(f){this.options=_.extend(this.options,f);if(this.options.can_add_library_item===true){$("#toolbtn_create_folder").show();$(".toolbtn_add_files").show()}if(this.options.contains_file===true){$("#toolbtn_bulk_import").show();$("#toolbtn_dl").show()}this.$el.find("[data-toggle]").tooltip()},createFolderFromModal:function(){event.preventDefault();event.stopPropagation();var f=this;var g=this.templateNewFolderInModal();this.modal=Galaxy.modal;this.modal.show({closing_events:true,title:"Create New Folder",body:g(),buttons:{Create:function(){f.create_new_folder_event()},Close:function(){Galaxy.modal.hide()}}})},create_new_folder_event:function(){var f=this.serialize_new_folder();if(this.validate_new_folder(f)){var h=new c.FolderAsModel();url_items=Backbone.history.fragment.split("/");current_folder_id=url_items[url_items.length-1];h.url=h.urlRoot+"/"+current_folder_id;var g=this;h.save(f,{success:function(i){g.modal.hide();e.success("Folder created");i.set({type:"folder"});Galaxy.libraries.folderListView.collection.add(i)},error:function(){e.error("An error occured :(")}})}else{e.error("Folder's name is missing")}return false},serialize_new_folder:function(){return{name:$("input[name='Name']").val(),description:$("input[name='Description']").val()}},validate_new_folder:function(f){return f.name!==""},modalBulkImport:function(){var f=$("#folder_table").find(":checked");if(f.length===0){e.info("You have to select some datasets first")}else{this.refreshUserHistoriesList(function(g){var h=g.templateBulkImportInModal();g.modal=Galaxy.modal;g.modal.show({closing_events:true,title:"Import into History",body:h({histories:g.histories.models}),buttons:{Import:function(){g.importAllIntoHistory()},Close:function(){Galaxy.modal.hide()}}})})}},refreshUserHistoriesList:function(g){var f=this;this.histories=new c.GalaxyHistories();this.histories.fetch({success:function(){g(f)},error:function(){}})},importAllIntoHistory:function(){this.modal.disableButton("Import");var j=$("select[name=dataset_import_bulk] option:selected").val();this.options.last_used_history_id=j;var m=$("select[name=dataset_import_bulk] option:selected").text();var o=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){o.push(this.parentElement.parentElement.id)}});var n=this.templateImportIntoHistoryProgressBar();this.modal.$el.find(".modal-body").html(n({history_name:m}));var k=100/o.length;this.initProgress(k);var f=[];for(var g=o.length-1;g>=0;g--){var h=o[g];var l=new c.HistoryItem();l.url=l.urlRoot+j+"/contents";l.content=h;l.source="library";f.push(l)}this.chainCall(f,m)},chainCall:function(g,j){var f=this;var h=g.pop();if(typeof h==="undefined"){e.success("Datasets were imported to history: "+j);this.modal.hide();return}var i=$.when(h.save({content:h.content,source:h.source}));i.done(function(k){f.updateProgress();f.chainCall(g,j)}).fail(function(k){e.error("An error occured :(");f.updateProgress();f.chainCall(g,j)})},initProgress:function(f){this.progress=0;this.progressStep=f},updateProgress:function(){this.progress+=this.progressStep;$(".progress-bar-import").width(Math.round(this.progress)+"%");txt_representation=Math.round(this.progress)+"% Complete";$(".completion_span").text(txt_representation)},download:function(f,j){var h=[];$("#folder_table").find(":checked").each(function(){if(this.parentElement.parentElement.id!==""){h.push(this.parentElement.parentElement.id)}});var g="/api/libraries/datasets/download/"+j;var i={ldda_ids:h};this.processDownload(g,i,"get")},processDownload:function(g,h,i){if(g&&h){h=typeof h==="string"?h:$.param(h);var f="";$.each(h.split("&"),function(){var j=this.split("=");f+='<input type="hidden" name="'+j[0]+'" value="'+j[1]+'" />'});$('<form action="'+g+'" method="'+(i||"post")+'">'+f+"</form>").appendTo("body").submit().remove();e.info("Your download will begin soon")}},addFilesToFolderModal:function(){this.refreshUserHistoriesList(function(f){f.modal=Galaxy.modal;var g=f.templateAddFilesInModal();f.modal.show({closing_events:true,title:"Add datasets from history to "+f.options.folder_name,body:g({histories:f.histories.models}),buttons:{Add:function(){f.addAllDatasetsFromHistory()},Close:function(){Galaxy.modal.hide()}}});if(f.histories.models.length>0){f.fetchAndDisplayHistoryContents(f.histories.models[0].id);$("#dataset_add_bulk").change(function(h){f.fetchAndDisplayHistoryContents(h.target.value)})}else{e.error("An error ocurred :(")}})},fetchAndDisplayHistoryContents:function(h){var g=new c.HistoryContents({id:h});var f=this;g.fetch({success:function(j){var i=f.templateHistoryContents();f.histories.get(h).set({contents:j});f.modal.$el.find("#selected_history_content").html(i({history_contents:j.models.reverse()}))},error:function(){e.error("An error ocurred :(")}})},addAllDatasetsFromHistory:function(){this.modal.disableButton("Add");var f=[];this.modal.$el.find("#selected_history_content").find(":checked").each(function(){var i=$(this.parentElement).data("id");if(i){f.push(i)}});var l=this.options.folder_name;var k=this.templateAddingDatasetsProgressBar();this.modal.$el.find(".modal-body").html(k({folder_name:l}));this.progressStep=100/f.length;this.progress=0;var j=[];for(var h=f.length-1;h>=0;h--){history_dataset_id=f[h];var g=new c.Item();g.url="/api/folders/"+this.options.id+"/contents";g.set({from_hda_id:history_dataset_id});j.push(g)}this.chainCallAddingHdas(j)},chainCallAddingHdas:function(g){var f=this;this.added_hdas=new c.Folder();var h=g.pop();if(typeof h==="undefined"){e.success("Datasets from history added to the folder");this.modal.hide();return this.added_hdas}var i=$.when(h.save({from_hda_id:h.get("from_hda_id")}));i.done(function(j){Galaxy.libraries.folderListView.collection.add(j);f.updateProgress();f.chainCallAddingHdas(g)}).fail(function(j){if(j.status===403){e.error("You are not allowed to access a dataset")}else{e.error("An error occured :(")}f.updateProgress();f.chainCallAddingHdas(g)})},templateToolBar:function(){tmpl_array=[];tmpl_array.push('<div class="library_style_container">');tmpl_array.push('<h3>Data Libraries Beta Test. This is work in progress. Please report problems & ideas via <a href="mailto:galaxy-bugs@bx.psu.edu?Subject=DataLibrariesBeta_Feedback" target="_blank">email</a> and <a href="https://trello.com/c/nwYQNFPK/56-data-library-ui-progressive-display-of-fol…" target="_blank">Trello</a>.</h3>');tmpl_array.push('<div id="library_folder_toolbar" >');tmpl_array.push('<div class="btn-group">');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Create New Folder" id="toolbtn_create_folder" class="btn btn-default primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-folder"></span></button>');tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Add Datasets to Current Folder" id="toolbtn_add_files" class="btn btn-default toolbtn_add_files primary-button" type="button" style="display:none;"><span class="fa fa-plus"></span><span class="fa fa-file"></span></span></button>');tmpl_array.push("</div>");tmpl_array.push(' <button data-toggle="tooltip" data-placement="top" title="Import selected datasets into history" id="toolbtn_bulk_import" class="primary-button" style="margin-left: 0.5em; " type="button"><span class="fa fa-book"></span> to history</button>');tmpl_array.push(' <div id="toolbtn_dl" class="btn-group" style="margin-left: 0.5em; ">');tmpl_array.push(' <button title="Download selected datasets" id="drop_toggle" type="button" class="primary-button dropdown-toggle" data-toggle="dropdown">');tmpl_array.push(' <span class="fa fa-download"></span> download <span class="caret"></span>');tmpl_array.push(" </button>");tmpl_array.push(' <ul class="dropdown-menu" role="menu">');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tgz">.tar.gz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/tbz">.tar.bz</a></li>');tmpl_array.push(' <li id="download_archive"><a href="#/folders/<%= id %>/download/zip">.zip</a></li>');tmpl_array.push(" </ul>");tmpl_array.push(" </div>");tmpl_array.push(" </div>");tmpl_array.push(' <div id="folder_items_element">');tmpl_array.push(" </div>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateNewFolderInModal:function(){tmpl_array=[];tmpl_array.push('<div id="new_folder_modal">');tmpl_array.push("<form>");tmpl_array.push('<input type="text" name="Name" value="" placeholder="Name">');tmpl_array.push('<input type="text" name="Description" value="" placeholder="Description">');tmpl_array.push("</form>");tmpl_array.push("</div>");return _.template(tmpl_array.join(""))},templateBulkImportInModal:function(){var f=[];f.push('<span id="history_modal_combo_bulk" style="width:90%; margin-left: 1em; margin-right: 1em; ">');f.push("Select history: ");f.push('<select id="dataset_import_bulk" name="dataset_import_bulk" style="width:50%; margin-bottom: 1em; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</span>");return _.template(f.join(""))},templateImportIntoHistoryProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Importing selected datasets to history <b><%= _.escape(history_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddingDatasetsProgressBar:function(){var f=[];f.push('<div class="import_text">');f.push("Adding selected datasets from history to library folder <b><%= _.escape(folder_name) %></b>");f.push("</div>");f.push('<div class="progress">');f.push(' <div class="progress-bar progress-bar-import" role="progressbar" aria-valuenow="0" aria-valuemin="0" aria-valuemax="100" style="width: 00%;">');f.push(' <span class="completion_span">0% Complete</span>');f.push(" </div>");f.push("</div>");f.push("");return _.template(f.join(""))},templateAddFilesInModal:function(){var f=[];f.push('<div id="add_files_modal">');f.push('<div id="history_modal_combo_bulk">');f.push("Select history: ");f.push('<select id="dataset_add_bulk" name="dataset_add_bulk" style="width:66%; "> ');f.push(" <% _.each(histories, function(history) { %>");f.push(' <option value="<%= _.escape(history.get("id")) %>"><%= _.escape(history.get("name")) %></option>');f.push(" <% }); %>");f.push("</select>");f.push("</div>");f.push('<div id="selected_history_content">');f.push("</div>");f.push("</div>");return _.template(f.join(""))},templateHistoryContents:function(){var f=[];f.push("Choose the datasets to import:");f.push("<ul>");f.push(" <% _.each(history_contents, function(history_item) { %>");f.push(' <li data-id="<%= _.escape(history_item.get("id")) %>">');f.push(' <input style="margin: 0;" type="checkbox"><%= _.escape(history_item.get("hid")) %>: <%= _.escape(history_item.get("name")) %>');f.push(" </li>");f.push(" <% }); %>");f.push("</ul>");return _.template(f.join(""))}});return{FolderToolbarView:a}});
\ No newline at end of file
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: QA, metrics-logger: finish tests for existing; casperjs: restore correct return value for loggedInAs
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/9fdf721e1ba1/
Changeset: 9fdf721e1ba1
User: carlfeberhard
Date: 2014-04-18 21:58:29
Summary: QA, metrics-logger: finish tests for existing; casperjs: restore correct return value for loggedInAs
Affected #: 4 files
diff -r e2dd42ca0708315efffd55479e68a81954b9c931 -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 static/scripts/packed/utils/metrics-logger.js
--- a/static/scripts/packed/utils/metrics-logger.js
+++ b/static/scripts/packed/utils/metrics-logger.js
@@ -1,1 +1,1 @@
-define([],function(){function h(z){z=z||{};var y=this;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){if(y.options.consoleLevel<=h.WARN){console.warn("Metrics logger could not stringify logArguments:",A,z);console.error(B)}}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,arguments)};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,arguments)};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,arguments)};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,arguments)};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,arguments)};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,arguments)};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}});
\ No newline at end of file
+define([],function(){function h(z){z=z||{};var y=this;y.userId=window.bootstrapped?window.bootstrapped.user.id:null;y.userId=y.userId||z.userId||null;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){y._emitToConsole("warn","MetricsLogger",["Metrics logger could not stringify logArguments:",A,z]);y._emitToConsole("error","MetricsLogger",[B])}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,Array.prototype.slice.call(arguments,0))};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}});
\ No newline at end of file
diff -r e2dd42ca0708315efffd55479e68a81954b9c931 -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 static/scripts/utils/metrics-logger.js
--- a/static/scripts/utils/metrics-logger.js
+++ b/static/scripts/utils/metrics-logger.js
@@ -33,7 +33,8 @@
//TODO: this might be used if we store the logs in browser storage
///** */
- //self.userId = options.userId || null;
+ self.userId = window.bootstrapped? window.bootstrapped.user.id: null;
+ self.userId = self.userId || options.userId || null;
/** the (optional) console to emit logs to */
self.consoleLogger = options.consoleLogger || null;
@@ -161,10 +162,10 @@
}
// discard entry if an error occurs, but warn if level set to do so
} catch( err ){
- if( self.options.consoleLevel <= MetricsLogger.WARN ){
- console.warn( 'Metrics logger could not stringify logArguments:', namespace, logArguments );
- console.error( err );
- }
+ self._emitToConsole( 'warn', 'MetricsLogger',
+ [ 'Metrics logger could not stringify logArguments:', namespace, logArguments ] );
+ self._emitToConsole( 'error', 'MetricsLogger', [ err ] );
+
}
return self;
};
@@ -268,34 +269,40 @@
//----------------------------------------------------------------------------- shortcuts
// generic functions when logging from non-namespaced object (e.g. templates)
+/** log to default namespace */
+MetricsLogger.prototype.log = function log(){
+ this.emit( 1, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
+};
+
/** debug to default namespace */
MetricsLogger.prototype.debug = function debug(){
- this.emit( MetricsLogger.DEBUG, this.options.defaultNamespace, arguments );
-};
-
-/** log to default namespace */
-MetricsLogger.prototype.log = function log(){
- this.emit( 1, this.options.defaultNamespace, arguments );
+ this.emit( MetricsLogger.DEBUG, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
};
/** info to default namespace */
MetricsLogger.prototype.info = function info(){
- this.emit( MetricsLogger.INFO, this.options.defaultNamespace, arguments );
+ this.emit( MetricsLogger.INFO, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
};
/** warn to default namespace */
MetricsLogger.prototype.warn = function warn(){
- this.emit( MetricsLogger.WARN, this.options.defaultNamespace, arguments );
+ this.emit( MetricsLogger.WARN, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
};
/** error to default namespace */
MetricsLogger.prototype.error = function error(){
- this.emit( MetricsLogger.ERROR, this.options.defaultNamespace, arguments );
+ this.emit( MetricsLogger.ERROR, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
};
/** metric to default namespace */
MetricsLogger.prototype.metric = function metric(){
- this.emit( MetricsLogger.METRIC, this.options.defaultNamespace, arguments );
+ this.emit( MetricsLogger.METRIC, this.options.defaultNamespace,
+ Array.prototype.slice.call( arguments, 0 ) );
};
diff -r e2dd42ca0708315efffd55479e68a81954b9c931 -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 test/casperjs/modules/user.js
--- a/test/casperjs/modules/user.js
+++ b/test/casperjs/modules/user.js
@@ -165,7 +165,7 @@
User.prototype.loggedInAs = function loggedInAs(){
var currUser = this.spaceghost.api.users.show( 'current' );
//this.spaceghost.debug( this.spaceghost.jsonStr( currUser ) );
- return currUser.email;
+ return currUser.email || '';
//TODO: due to late rendering of masthead this is no longer reliable - need a wait for in the main page
//return this.spaceghost.jumpToTop( function(){
// var userEmail = '';
diff -r e2dd42ca0708315efffd55479e68a81954b9c931 -r 9fdf721e1ba10ffafd5a3c37e535809e1682cbb9 test/qunit/tests/metrics-logger.js
--- a/test/qunit/tests/metrics-logger.js
+++ b/test/qunit/tests/metrics-logger.js
@@ -17,7 +17,9 @@
self.lastMessage = null;
[ 'log', 'debug', 'info', 'warn', 'error' ].forEach( function( fnName ){
self[ fnName ] = function(){
- self.lastMessage = { level: fnName, args: Array.prototype.slice.call( arguments, 0 ) };
+ var args = Array.prototype.slice.call( arguments, 0 );
+ //console.debug( 'MockConsole:', fnName, JSON.stringify( args ) );
+ self.lastMessage = { level: fnName, args: args };
};
});
};
@@ -171,6 +173,70 @@
server.restore();
});
+ // ------------------------------------------------------------------------ Emit to console
+ test( "emit to console at level", function() {
+ var mockConsole = new MockConsole(),
+ logger = new metrics.MetricsLogger({
+ consoleLevel : 'debug',
+ consoleLogger : mockConsole
+ });
+ equal( logger.options.consoleLevel, metrics.MetricsLogger.DEBUG );
+ equal( logger.consoleLogger.constructor, MockConsole );
+
+ logger.emit( 'debug', 'test', [ 1, 2, { three: 3 }] );
+ equal( logger.cache.length(), 0 );
+ //console.debug( JSON.stringify( mockConsole.lastMessage ) );
+ equal( mockConsole.lastMessage.level, 'debug' );
+ equal( mockConsole.lastMessage.args.length, 4 );
+ equal( mockConsole.lastMessage.args[0], 'test' );
+ equal( mockConsole.lastMessage.args[3].three, 3 );
+ });
+
+ test( "emit to console below does not output", function() {
+ var mockConsole = new MockConsole(),
+ logger = new metrics.MetricsLogger({
+ consoleLevel : 'error',
+ consoleLogger : mockConsole
+ });
+ logger.emit( 'debug', 'test', [ 1, 2, { three: 3 }] );
+ equal( mockConsole.lastMessage, null );
+ });
+
+ // ------------------------------------------------------------------------ Shortcuts
+ test( "logger shortcuts emit to default namespace properly", function() {
+ var logger = new metrics.MetricsLogger({
+ logLevel : 'all'
+ });
+ equal( logger.options.logLevel, metrics.MetricsLogger.ALL );
+ logger.log( 0 );
+ logger.debug( 1 );
+ logger.info( 2 );
+ logger.warn( 3 );
+ logger.error( 4 );
+ logger.metric( 5 );
+
+ equal( logger.cache.length(), 6 );
+ var cached = logger.cache.remove( 6 ).map( JSON.parse ),
+ entry;
+
+ cached.forEach( function( entry ){
+ ok( entry.namespace === logger.options.clientPrefix + logger.options.defaultNamespace );
+ ok( jQuery.type( entry.args ) === 'array' );
+ ok( typeof entry.time === 'string' );
+ });
+
+ // log is different
+ entry = cached[0];
+ ok( entry.level === 1 );
+ ok( entry.args[0] === 0 );
+
+ [ 'debug', 'info', 'warn', 'error', 'metric' ].forEach( function( level, i ){
+ entry = cached[( i + 1 )];
+ ok( entry.level === logger._parseLevel( level ) );
+ ok( entry.args[0] === ( i + 1 ) );
+ });
+ });
+
// ======================================================================== LoggingCache
test( "cache construction/initializiation defaults", function() {
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
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e2dd42ca0708/
Changeset: e2dd42ca0708
User: davebgx
Date: 2014-04-18 20:58:04
Summary: Merge fix from stable.
Affected #: 3 files
diff -r 1d5f72128929f5ee2f982dd26ff94f7cc4f33610 -r e2dd42ca0708315efffd55479e68a81954b9c931 lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1713,9 +1713,11 @@
changeset_revision = kwd.get( 'changeset_revision', None )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
repository_id = trans.security.encode_id( repository.id )
- # We aren't concerned with repository's of type tool_dependency_definition here if a repository_metadata record is not returned
- # because repositories of this type will never have repository dependencies.
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ # We aren't concerned with repositories of type tool_dependency_definition here if a repository_metadata record is not returned
+ # because repositories of this type will never have repository dependencies. However, if a readme file is uploaded, or some other
+ # change is made that does not create a new downloadable changeset revision but updates the existing one, we still want to be able
+ # to get repository dependencies.
+ repository_metadata = suc.get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
if metadata:
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
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/1d5f72128929/
Changeset: 1d5f72128929
User: guerler
Date: 2014-04-18 20:53:48
Summary: Charts: Update nvd3
Affected #: 1 file
This diff is so big that we needed to truncate the remainder.
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: davebgx: If a tool shed repository was updated after a tool migration without a new installable changeset revision being generated, for example by adding or removing a readme file, the migration install framework would be unable to find repository dependencies. This changeset resolves that.
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/e6876f691854/
Changeset: e6876f691854
Branch: stable
User: davebgx
Date: 2014-04-18 19:58:51
Summary: If a tool shed repository was updated after a tool migration without a new installable changeset revision being generated, for example by adding or removing a readme file, the migration install framework would be unable to find repository dependencies. This changeset resolves that.
Affected #: 1 file
diff -r 5fd196b5d1760d1a8180184f8e5450e0957b37c2 -r e6876f6918548a0805fa0cc5306ba1ced6fb184a lib/galaxy/webapps/tool_shed/controllers/repository.py
--- a/lib/galaxy/webapps/tool_shed/controllers/repository.py
+++ b/lib/galaxy/webapps/tool_shed/controllers/repository.py
@@ -1700,9 +1700,11 @@
changeset_revision = kwd.get( 'changeset_revision', None )
repository = suc.get_repository_by_name_and_owner( trans.app, name, owner )
repository_id = trans.security.encode_id( repository.id )
- # We aren't concerned with repository's of type tool_dependency_definition here if a repository_metadata record is not returned
- # because repositories of this type will never have repository dependencies.
- repository_metadata = suc.get_repository_metadata_by_changeset_revision( trans, repository_id, changeset_revision )
+ # We aren't concerned with repositories of type tool_dependency_definition here if a repository_metadata record is not returned
+ # because repositories of this type will never have repository dependencies. However, if a readme file is uploaded, or some other
+ # change is made that does not create a new downloadable changeset revision but updates the existing one, we still want to be able
+ # to get repository dependencies.
+ repository_metadata = suc.get_current_repository_metadata_for_changeset_revision( trans, repository, changeset_revision )
if repository_metadata:
metadata = repository_metadata.metadata
if metadata:
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: QA, metrics logger: test metrics post
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/f5bfac95df59/
Changeset: f5bfac95df59
User: carlfeberhard
Date: 2014-04-18 20:42:26
Summary: QA, metrics logger: test metrics post
Affected #: 1 file
diff -r 4603eccf8a589d5f0b77e1484cf42c1420c75c57 -r f5bfac95df59c8dd436deae60d6bb9fc7593f4da test/qunit/tests/metrics-logger.js
--- a/test/qunit/tests/metrics-logger.js
+++ b/test/qunit/tests/metrics-logger.js
@@ -23,7 +23,6 @@
};
module( "Metrics logger tests" );
-
// ======================================================================== MetricsLogger
test( "logger construction/initializiation defaults", function() {
var logger = new metrics.MetricsLogger({});
@@ -95,7 +94,84 @@
logger.emit( 'metric', 'test', [{ window: window }] );
equal( logger.cache.length(), 0 );
});
-
+
+ function metricsFromRequestBody( request ){
+ // assumes 'metrics' is only entry in requestBody
+ return JSON.parse( decodeURIComponent( request.requestBody.replace( 'metrics=', '' ) ) );
+ }
+
+ test( "_postCache success", function () {
+ var callback = sinon.spy(),
+ logger = new metrics.MetricsLogger({
+ logLevel : 'metric',
+ onServerResponse : function( response ){ callback(); }
+ });
+
+ var server = sinon.fakeServer.create(),
+ metricsOnServer;
+ server.respondWith( 'POST', '/api/metrics', function( request ){
+ metricsOnServer = metricsFromRequestBody( request );
+ request.respond(
+ 200,
+ { "Content-Type": "application/json" },
+ JSON.stringify({
+ fakeResponse: 'yes'
+ })
+ );
+ });
+
+ logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] );
+ logger._postCache();
+ server.respond();
+ ok( callback.calledOnce, 'onServerResponse was called' );
+ equal( logger.cache.length(), 0, 'should have emptied cache (on success)' );
+ equal( logger._postSize, 1000, '_postSize still at default' );
+
+ // metrics were in proper form on server
+ equal( metricsOnServer.length, 1 );
+ var metric = metricsOnServer[0];
+ equal( metric.level, metrics.MetricsLogger.METRIC );
+ equal( metric.namespace, 'client.test' );
+ equal( metric.args.length, 3 );
+ equal( metric.args[2].three, 3 );
+ ok( typeof metric.time === 'string' );
+ ok( metric.time === new Date( metric.time ).toISOString() );
+
+ server.restore();
+ });
+
+ test( "_postCache failure", function () {
+ var callback = sinon.spy(),
+ logger = new metrics.MetricsLogger({
+ logLevel : 'metric',
+ onServerResponse : function( response ){ callback(); }
+ });
+
+ var server = sinon.fakeServer.create();
+ server.respondWith( 'POST', '/api/metrics', function( request ){
+ request.respond(
+ 500,
+ { "Content-Type": "application/json" },
+ JSON.stringify({
+ err_msg: 'NoooOPE!'
+ })
+ );
+ });
+
+ logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] );
+ logger._postCache();
+ server.respond();
+ //TODO: is the following what we want?
+ ok( !callback.calledOnce, 'onServerResponse was NOT called' );
+ equal( logger.cache.length(), 1, 'should NOT have emptied cache' );
+ equal( logger._postSize, logger.options.maxCacheSize, '_postSize changed to max' );
+
+ //TODO: still doesn't solve the problem that when cache == max, post will be tried on every emit
+
+ server.restore();
+ });
+
+
// ======================================================================== LoggingCache
test( "cache construction/initializiation defaults", function() {
var cache = new metrics.LoggingCache();
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Update NGS read simulator to use job working directory.
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/4603eccf8a58/
Changeset: 4603eccf8a58
User: dan
Date: 2014-04-18 19:31:13
Summary: Update NGS read simulator to use job working directory.
Affected #: 1 file
diff -r 2edb06612c92b7e259e710f63b5cd15d4805c490 -r 4603eccf8a589d5f0b77e1484cf42c1420c75c57 tools/ngs_simulation/ngs_simulation.xml
--- a/tools/ngs_simulation/ngs_simulation.xml
+++ b/tools/ngs_simulation/ngs_simulation.xml
@@ -7,7 +7,7 @@
--input="${in_type.genome.fields.path}"
--genome=$in_type.genome
#else
- --input=$in_type.input1
+ --input="${ in_type.input1 }"
#end if
--read_len=$read_len
--avg_coverage=$avg_coverage
@@ -15,10 +15,10 @@
--num_sims=$num_sims
--polymorphism=$polymorphism
--detection_thresh=$detection_thresh
- --output_png=$output_png
+ --output_png="${ output_png }"
--summary_out=$summary_out
- --output_summary=$output_summary
- --new_file_path=$__new_file_path__
+ --output_summary="${ output_summary }"
+ --new_file_path="."
</command><!-- If want to include all simulation results file
sim_results=$sim_results
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Update MAF to BED to use job working directory and built-in primary dataset collection.
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/2edb06612c92/
Changeset: 2edb06612c92
User: dan
Date: 2014-04-18 19:23:38
Summary: Update MAF to BED to use job working directory and built-in primary dataset collection.
Affected #: 3 files
diff -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 -r 2edb06612c92b7e259e710f63b5cd15d4805c490 tools/maf/maf_to_bed.py
--- a/tools/maf/maf_to_bed.py
+++ b/tools/maf/maf_to_bed.py
@@ -19,6 +19,7 @@
species = sys.argv[3].split(',')
partial = sys.argv[4]
+ output_id = sys.argv[6]
out_files = {}
primary_spec = None
@@ -47,10 +48,7 @@
out_files[spec] = open( output_filename, 'w' )
primary_spec = spec
else:
- out_files[spec] = tempfile.NamedTemporaryFile( mode = 'w', dir = database_tmp_dir, suffix = '.maf_to_bed' )
- filename = out_files[spec].name
- out_files[spec].close()
- out_files[spec] = open( filename, 'w' )
+ out_files[ spec ] = open( os.path.join( database_tmp_dir, 'primary_%s_%s_visible_bed_%s' % ( output_id, spec, spec ) ), 'wb+' )
num_species = len( species )
print "Restricted to species:", ",".join( species )
@@ -71,10 +69,7 @@
if not spec or not chrom:
spec = chrom = c.src
if spec not in out_files.keys():
- out_files[spec] = tempfile.NamedTemporaryFile( mode='w', dir = database_tmp_dir, suffix = '.maf_to_bed' )
- filename = out_files[spec].name
- out_files[spec].close()
- out_files[spec] = open( filename, 'w' )
+ out_files[ spec ] = open( os.path.join( database_tmp_dir, 'primary_%s_%s_visible_bed_%s' % ( output_id, spec, spec ) ), 'wb+' )
if c.strand == "-":
out_files[spec].write( chrom + "\t" + str( c.src_size - c.end ) + "\t" + str( c.src_size - c.start ) + "\t" + spec + "_" + str( block_num ) + "\t" + "0\t" + c.strand + "\n" )
@@ -85,10 +80,6 @@
for file_out in out_files.keys():
out_files[file_out].close()
- for spec in out_files.keys():
- if spec != primary_spec:
- print "#FILE\t" + spec + "\t" + os.path.join( database_tmp_dir, os.path.split( out_files[spec].name )[1] )
- else:
- print "#FILE1\t" + spec + "\t" + out_files[spec].name
+ print "#FILE1_DBKEY\t%s" % ( primary_spec )
if __name__ == "__main__": __main__()
diff -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 -r 2edb06612c92b7e259e710f63b5cd15d4805c490 tools/maf/maf_to_bed.xml
--- a/tools/maf/maf_to_bed.xml
+++ b/tools/maf/maf_to_bed.xml
@@ -1,6 +1,6 @@
-<tool id="MAF_To_BED1" name="Maf to BED" force_history_refresh="True">
+<tool id="MAF_To_BED1" name="MAF to BED" force_history_refresh="True"><description>Converts a MAF formatted file to the BED format</description>
- <command interpreter="python">maf_to_bed.py $input1 $out_file1 $species $complete_blocks $__new_file_path__</command>
+ <command interpreter="python">maf_to_bed.py "${ input1 }" "${ out_file1 }" "${ species }" "${ complete_blocks }" "." "${ out_file1.id }"</command><inputs><param format="maf" name="input1" type="data" label="MAF file to convert"/><param name="species" type="select" label="Select species" display="checkboxes" multiple="true" help="a separate history item will be created for each checked species">
diff -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 -r 2edb06612c92b7e259e710f63b5cd15d4805c490 tools/maf/maf_to_bed_code.py
--- a/tools/maf/maf_to_bed_code.py
+++ b/tools/maf/maf_to_bed_code.py
@@ -6,56 +6,20 @@
def exec_after_process(app, inp_data, out_data, param_dict, tool, stdout, stderr):
output_data = out_data.items()[0][1]
- history = output_data.history
- if history == None:
- print "unknown history!"
- return
new_stdout = ""
split_stdout = stdout.split("\n")
- basic_name = output_data.name
- output_data_list = []
for line in split_stdout:
if line.startswith("#FILE1"):
fields = line.split("\t")
dbkey = fields[1]
- filepath = fields[2]
output_data.dbkey = dbkey
- output_data.name = basic_name + " (" + dbkey + ")"
+ output_data.name = "%s (%s)" % ( output_data.name, dbkey )
app.model.context.add( output_data )
app.model.context.flush()
- output_data_list.append(output_data)
- elif line.startswith("#FILE"):
- fields = line.split("\t")
- dbkey = fields[1]
- filepath = fields[2]
- newdata = app.model.HistoryDatasetAssociation( create_dataset = True, sa_session = app.model.context )
- newdata.set_size()
- newdata.extension = "bed"
- newdata.name = basic_name + " (" + dbkey + ")"
- app.model.context.add( newdata )
- app.model.context.flush()
- history.add_dataset( newdata )
- app.security_agent.copy_dataset_permissions( output_data.dataset, newdata.dataset )
- app.model.context.add( history )
- app.model.context.flush()
- try:
- app.object_store.update_from_file( newdata.dataset, file_name=filepath, create=True )
- os.unlink( filepath )
- newdata.info = newdata.name
- newdata.state = newdata.states.OK
- except:
- newdata.info = "The requested file is missing from the system."
- newdata.state = newdata.states.ERROR
- newdata.dbkey = dbkey
- newdata.init_meta()
- newdata.set_meta()
- newdata.set_peek()
- app.model.context.flush()
- output_data_list.append(newdata)
else:
- new_stdout = new_stdout + line
- for data in output_data_list:
- if data.state == data.states.OK:
- data.info = new_stdout
- app.model.context.add( data )
- app.model.context.flush()
+ new_stdout = "%s\n%s" % ( new_stdout, line )
+ for data in output_data.creating_job.output_datasets:
+ data = data.dataset
+ data.info = new_stdout
+ app.model.context.add( data )
+ app.model.context.flush()
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: carlfeberhard: QA: more testing of metrics logger
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/bc34e6a879f7/
Changeset: bc34e6a879f7
User: carlfeberhard
Date: 2014-04-18 18:58:20
Summary: QA: more testing of metrics logger
Affected #: 4 files
diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/packed/galaxy-app-base.js
--- a/static/scripts/packed/galaxy-app-base.js
+++ b/static/scripts/packed/galaxy-app-base.js
@@ -1,1 +1,1 @@
-define(["mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization","bootstrapped-data"],function(b,d,g,e,a){function h(n){var m=this;return m._init(n||{})}g(h,"GalaxyApp");h.prototype.defaultOptions={patchExisting:true,root:"/"};h.prototype._init=function k(n){var m=this;_.extend(m,Backbone.Events);m._processOptions(n);m.debug("GalaxyApp.options: ",m.options);m._patchGalaxy(window.Galaxy);m.debug("GalaxyApp.options: ",m.options);m._initLogger(n.loggerOptions||{});m.debug("GalaxyApp.logger: ",m.logger);m._initLocale();m.debug("GalaxyApp.localize: ",m.localize);m.config=n.config||a.config||{};m.debug("GalaxyApp.config: ",m.config);m._initUser(n.user||a.user||{});m.debug("GalaxyApp.user: ",m.user);m.trigger("ready",m);return m};h.prototype._processOptions=function f(o){var n=this,p=n.defaultOptions;n.debug("_processOptions: ",o);n.options={};for(var m in p){if(p.hasOwnProperty(m)){n.options[m]=(o.hasOwnProperty(m))?(o[m]):(p[m])}}return n};h.prototype._patchGalaxy=function f(m){var o=this;if(o.options.patchExisting&&m){o.debug("found existing Galaxy object:",m);for(var n in m){if(m.hasOwnProperty(n)){o.debug("\t patching in "+n+" to Galaxy");o[n]=m[n]}}}};h.prototype._initLogger=function l(n){var m=this;m.debug("_initLogger:",n);m.logger=new d.MetricsLogger(n);return m};h.prototype._initLocale=function j(n){var m=this;m.debug("_initLocale:",n);m.localize=e;window._l=m.localize;return m};h.prototype._initUser=function i(n){var m=this;m.debug("_initUser:",n);m.user=new b.User(n);m.currUser=m.user;return m};h.prototype.toString=function c(){var m=this.user.get("email")||"(anonymous)";return"GalaxyApp("+m+")"};return{GalaxyApp:h}});
\ No newline at end of file
+define(["mvc/user/user-model","utils/metrics-logger","utils/add-logging","utils/localization","bootstrapped-data"],function(b,d,g,e,a){function h(n){var m=this;return m._init(n||{})}g(h,"GalaxyApp");h.prototype.defaultOptions={patchExisting:true,root:"/"};h.prototype._init=function k(n){var m=this;_.extend(m,Backbone.Events);m._processOptions(n);m.debug("GalaxyApp.options: ",m.options);m._patchGalaxy(window.Galaxy);m._initLogger(n.loggerOptions||{});m.debug("GalaxyApp.logger: ",m.logger);m._initLocale();m.debug("GalaxyApp.localize: ",m.localize);m.config=n.config||a.config||{};m.debug("GalaxyApp.config: ",m.config);m._initUser(n.user||a.user||{});m.debug("GalaxyApp.user: ",m.user);m.trigger("ready",m);return m};h.prototype._processOptions=function f(o){var n=this,p=n.defaultOptions;n.debug("_processOptions: ",o);n.options={};for(var m in p){if(p.hasOwnProperty(m)){n.options[m]=(o.hasOwnProperty(m))?(o[m]):(p[m])}}return n};h.prototype._patchGalaxy=function f(m){var o=this;if(o.options.patchExisting&&m){o.debug("found existing Galaxy object:",m);for(var n in m){if(m.hasOwnProperty(n)){o.debug("\t patching in "+n+" to Galaxy");o[n]=m[n]}}}};h.prototype._initLogger=function l(n){var m=this;m.debug("_initLogger:",n);m.logger=new d.MetricsLogger(n);return m};h.prototype._initLocale=function j(n){var m=this;m.debug("_initLocale:",n);m.localize=e;window._l=m.localize;return m};h.prototype._initUser=function i(n){var m=this;m.debug("_initUser:",n);m.user=new b.User(n);m.currUser=m.user;return m};h.prototype.toString=function c(){var m=this.user.get("email")||"(anonymous)";return"GalaxyApp("+m+")"};return{GalaxyApp:h}});
\ No newline at end of file
diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/packed/utils/metrics-logger.js
--- a/static/scripts/packed/utils/metrics-logger.js
+++ b/static/scripts/packed/utils/metrics-logger.js
@@ -1,1 +1,1 @@
-define([],function(){function h(z){z=z||{};var y=this;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){if(y.options.consoleLevel<=h.WARN){console.warn("Metrics logger could not stringify logArguments:",A,z);console.error(B)}}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);console.debug("removed entries:",C,"size now:",A.cache.length());A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,arguments)};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,arguments)};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,arguments)};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,arguments)};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,arguments)};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,arguments)};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}});
\ No newline at end of file
+define([],function(){function h(z){z=z||{};var y=this;y.consoleLogger=z.consoleLogger||null;y._init(z);return y}h.ALL=0;h.DEBUG=10;h.INFO=20;h.WARN=30;h.ERROR=40;h.METRIC=50;h.NONE=100;h.defaultOptions={logLevel:h.NONE,consoleLevel:h.NONE,defaultNamespace:"Galaxy",clientPrefix:"client.",maxCacheSize:3000,postSize:1000,addTime:true,postUrl:"/api/metrics",getPingData:undefined,onServerResponse:undefined};h.prototype._init=function i(A){var z=this;z.options={};for(var y in h.defaultOptions){if(h.defaultOptions.hasOwnProperty(y)){z.options[y]=(A.hasOwnProperty(y))?(A[y]):(h.defaultOptions[y])}}z.options.logLevel=z._parseLevel(z.options.logLevel);z.options.consoleLevel=z._parseLevel(z.options.consoleLevel);z._sending=false;z._postSize=z.options.postSize;z._initCache();return z};h.prototype._initCache=function a(){this.cache=new w({maxSize:this.options.maxCacheSize})};h.prototype._parseLevel=function j(A){var z=typeof A;if(z==="number"){return A}if(z==="string"){var y=A.toUpperCase();if(h.hasOwnProperty(y)){return h[y]}}throw new Error("Unknown log level: "+A)};h.prototype.emit=function m(B,A,z){var y=this;A=A||y.options.defaultNamespace;if(!B||!z){return y}B=y._parseLevel(B);if(B>=y.options.logLevel){y._addToCache(B,A,z)}if(y.consoleLogger&&B>=y.options.consoleLevel){y._emitToConsole(B,A,z)}return y};h.prototype._addToCache=function b(D,A,z){this._emitToConsole("debug","MetricsLogger",["_addToCache:",arguments,this.options.addTime,this.cache.length()]);var y=this;try{var C=y.cache.add(y._buildEntry(D,A,z));if(C>=y._postSize){y._postCache()}}catch(B){if(y.options.consoleLevel<=h.WARN){console.warn("Metrics logger could not stringify logArguments:",A,z);console.error(B)}}return y};h.prototype._buildEntry=function r(B,z,y){this._emitToConsole("debug","MetricsLogger",["_buildEntry:",arguments]);var A={level:B,namespace:this.options.clientPrefix+z,args:y};if(this.options.addTime){A.time=new Date().toISOString()}return A};h.prototype._postCache=function s(B){B=B||{};this._emitToConsole("info","MetricsLogger",["_postCache",B,this._postSize]);if(!this.options.postUrl||this._sending){return jQuery.when({})}var A=this,D=B.count||A._postSize,y=A.cache.get(D),C=y.length,z=(typeof A.options.getPingData==="function")?(A.options.getPingData()):({});z.metrics=A._preprocessCache(y);A._sending=true;return jQuery.post(A.options.postUrl,z).always(function(){A._sending=false}).fail(function(){A._postSize=A.options.maxCacheSize}).done(function(E){if(typeof A.options.onServerResponse==="function"){A.options.onServerResponse(E)}A.cache.remove(C);A._postSize=A.options.postSize})};h.prototype._preprocessCache=function f(y){return["[",(y.join(",\n")),"]"].join("\n")};h.prototype._emitToConsole=function c(C,B,A){var y=this;if(!y.consoleLogger){return y}var z=Array.prototype.slice.call(A,0);z.unshift(B);if(C>=h.METRIC&&typeof(y.consoleLogger.info)==="function"){return y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.ERROR&&typeof(y.consoleLogger.error)==="function"){return y.consoleLogger.error.apply(y.consoleLogger,z)}else{if(C>=h.WARN&&typeof(y.consoleLogger.warn)==="function"){y.consoleLogger.warn.apply(y.consoleLogger,z)}else{if(C>=h.INFO&&typeof(y.consoleLogger.info)==="function"){y.consoleLogger.info.apply(y.consoleLogger,z)}else{if(C>=h.DEBUG&&typeof(y.consoleLogger.debug)==="function"){y.consoleLogger.debug.apply(y.consoleLogger,z)}else{if(typeof(y.consoleLogger.log)==="function"){y.consoleLogger.log.apply(y.consoleLogger,z)}}}}}}return y};h.prototype.debug=function l(){this.emit(h.DEBUG,this.options.defaultNamespace,arguments)};h.prototype.log=function g(){this.emit(1,this.options.defaultNamespace,arguments)};h.prototype.info=function u(){this.emit(h.INFO,this.options.defaultNamespace,arguments)};h.prototype.warn=function t(){this.emit(h.WARN,this.options.defaultNamespace,arguments)};h.prototype.error=function p(){this.emit(h.ERROR,this.options.defaultNamespace,arguments)};h.prototype.metric=function n(){this.emit(h.METRIC,this.options.defaultNamespace,arguments)};function w(z){var y=this;y._cache=[];return y._init(z||{})}w.defaultOptions={maxSize:5000};w.prototype._init=function i(y){this.maxSize=y.maxSize||w.defaultOptions.maxSize;return this};w.prototype.add=function k(A){var z=this,y=(z.length()+1)-z.maxSize;if(y>0){z.remove(y)}z._cache.push(z._preprocessEntry(A));return z.length()};w.prototype._preprocessEntry=function q(y){return JSON.stringify(y)};w.prototype.length=function e(){return this._cache.length};w.prototype.get=function v(y){return this._cache.slice(0,y)};w.prototype.remove=function x(y){return this._cache.splice(0,y)};w.prototype.stringify=function o(y){return["[",(this.get(y).join(",\n")),"]"].join("\n")};w.prototype.print=function d(){this._cache.forEach(function(y){console.log(y)})};return{MetricsLogger:h,LoggingCache:w}});
\ No newline at end of file
diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 static/scripts/utils/metrics-logger.js
--- a/static/scripts/utils/metrics-logger.js
+++ b/static/scripts/utils/metrics-logger.js
@@ -224,7 +224,7 @@
}
// only remove if post successful
self.cache.remove( entriesLength );
- console.debug( 'removed entries:', entriesLength, 'size now:', self.cache.length() );
+ //console.debug( 'removed entries:', entriesLength, 'size now:', self.cache.length() );
// if we succeeded, reset the post target to the normal num of entries
self._postSize = self.options.postSize;
});
diff -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 -r bc34e6a879f7ec7a4e63e9a2cd858b89dda16761 test/qunit/tests/metrics-logger.js
--- a/test/qunit/tests/metrics-logger.js
+++ b/test/qunit/tests/metrics-logger.js
@@ -9,11 +9,22 @@
$,
sinon
){
- /*globals equal test module expect deepEqual strictEqual throws */
+ /*globals equal test module expect deepEqual strictEqual throws ok */
"use strict";
+ var MockConsole = function(){
+ var self = this;
+ self.lastMessage = null;
+ [ 'log', 'debug', 'info', 'warn', 'error' ].forEach( function( fnName ){
+ self[ fnName ] = function(){
+ self.lastMessage = { level: fnName, args: Array.prototype.slice.call( arguments, 0 ) };
+ };
+ });
+ };
+
module( "Metrics logger tests" );
+ // ======================================================================== MetricsLogger
test( "logger construction/initializiation defaults", function() {
var logger = new metrics.MetricsLogger({});
equal( logger.consoleLogger, null );
@@ -24,6 +35,9 @@
equal( logger.options.postSize, 1000 );
equal( logger.options.maxCacheSize, 3000 );
equal( logger.options.addTime, true );
+ equal( logger.options.postUrl, '/api/metrics' );
+ equal( logger.options.getPingData, undefined );
+ equal( logger.options.onServerResponse, undefined );
equal( logger._postSize, 1000 );
equal( logger.cache.constructor, metrics.LoggingCache );
@@ -47,10 +61,105 @@
logger._parseLevel( 'nope' );
}, /Unknown log level/, 'Unknown log level throws error' );
});
+
+ // ------------------------------------------------------------------------ Emit to cache
+ test( "emit to cache at level", function() {
+ var logger = new metrics.MetricsLogger({
+ logLevel : 'metric'
+ });
+ equal( logger.options.logLevel, metrics.MetricsLogger.METRIC );
+ logger.emit( 'metric', 'test', [ 1, 2, { three: 3 }] );
+ equal( logger.cache.length(), 1 );
+
+ var cached = JSON.parse( logger.cache.get( 1 ) );
+ equal( cached.level, metrics.MetricsLogger.METRIC );
+ equal( cached.namespace, 'client.test' );
+ equal( cached.args.length, 3 );
+ equal( cached.args[2].three, 3 );
+ ok( typeof cached.time === 'string' );
+ ok( cached.time === new Date( cached.time ).toISOString() );
+ });
+
+ test( "emit to cache below does not cache", function() {
+ var logger = new metrics.MetricsLogger({
+ logLevel : 'metric'
+ });
+ logger.emit( 'error', 'test', [ 1, 2, { three: 3 }] );
+ equal( logger.cache.length(), 0 );
+ });
+
+ test( "emit to cache (silently) drops non-parsable", function() {
+ var logger = new metrics.MetricsLogger({
+ logLevel : 'metric'
+ });
+ logger.emit( 'metric', 'test', [{ window: window }] );
+ equal( logger.cache.length(), 0 );
+ });
+ // ======================================================================== LoggingCache
test( "cache construction/initializiation defaults", function() {
var cache = new metrics.LoggingCache();
equal( cache.maxSize, 5000 );
equal( $.type( cache._cache ), 'array' );
});
+
+ test( "cache construction/initializiation setting max cache size", function() {
+ var cache = new metrics.LoggingCache({
+ maxSize : 5
+ });
+ equal( cache.maxSize, 5 );
+ });
+
+ test( "cache plays well with no data", function() {
+ var cache = new metrics.LoggingCache();
+
+ equal( cache._cache.length, 0 );
+ equal( cache.length(), 0 );
+ var get = cache.get( 10 );
+ ok( jQuery.type( get ) === 'array' && get.length === 0 );
+ var remove = cache.remove( 10 );
+ ok( jQuery.type( remove ) === 'array' && remove.length === 0 );
+ equal( cache.length(), 0 );
+ });
+
+ test( "cache add properly adds and removes data", function() {
+ var cache = new metrics.LoggingCache({
+ maxSize : 5
+ });
+ var entry1 = [{ one: 1 }, 'two' ];
+ cache.add( entry1 );
+
+ equal( cache._cache.length, 1 );
+ equal( cache.length(), 1 );
+ equal( cache._cache[0], JSON.stringify( entry1 ) );
+ equal( cache.get( 1 ), JSON.stringify( entry1 ) );
+
+ var entry2 = { blah: { one: 1 }, bler: [ 'three', { two: 2 } ] };
+ cache.add( entry2 );
+ equal( cache.length(), 2 );
+ equal( cache.stringify( 2 ), '[\n' + JSON.stringify( entry1 ) + ',\n' + JSON.stringify( entry2 ) + '\n]' );
+
+ // FIFO
+ var returned = cache.remove( 1 );
+ equal( cache.length(), 1 );
+ ok( jQuery.type( returned ) === 'array' && returned.length === 1 );
+ var returned0 = returned[0];
+ ok( jQuery.type( returned0 ) === 'string' && returned0 === JSON.stringify( entry1 ) );
+ });
+
+ test( "cache past max loses oldest", function() {
+ var cache = new metrics.LoggingCache({
+ maxSize : 5
+ });
+ for( var i=0; i<10; i+=1 ){
+ cache.add({ index: i });
+ }
+ equal( cache.length(), 5 );
+ var get = cache.get( 5 );
+ ok( JSON.parse( get[0] ).index === 5 );
+ ok( JSON.parse( get[1] ).index === 6 );
+ ok( JSON.parse( get[2] ).index === 7 );
+ ok( JSON.parse( get[3] ).index === 8 );
+ ok( JSON.parse( get[4] ).index === 9 );
+ });
});
Repository URL: https://bitbucket.org/galaxy/galaxy-central/
--
This is a commit notification from bitbucket.org. You are receiving
this because you have the service enabled, addressing the recipient of
this email.
1
0
commit/galaxy-central: dan: Update MAF to interval to use job working directory instead of __new_file_path__.
by commits-noreply@bitbucket.org 18 Apr '14
by commits-noreply@bitbucket.org 18 Apr '14
18 Apr '14
1 new commit in galaxy-central:
https://bitbucket.org/galaxy/galaxy-central/commits/47285f0d20f4/
Changeset: 47285f0d20f4
User: dan
Date: 2014-04-18 18:34:08
Summary: Update MAF to interval to use job working directory instead of __new_file_path__.
Affected #: 1 file
diff -r a7e0eb001bc4c20ef69815c11c0098366b0bfb4d -r 47285f0d20f4cbcb150a894f343fd8cbf1bed4a7 tools/maf/maf_to_interval.xml
--- a/tools/maf/maf_to_interval.xml
+++ b/tools/maf/maf_to_interval.xml
@@ -1,6 +1,6 @@
<tool id="MAF_To_Interval1" name="MAF to Interval" force_history_refresh="True"><description>Converts a MAF formatted file to the Interval format</description>
- <command interpreter="python">maf_to_interval.py $input1 $out_file1 $out_file1.id $__new_file_path__ $input1.dbkey $species $input1.metadata.species $complete_blocks $remove_gaps</command>
+ <command interpreter="python">maf_to_interval.py "${ input1 }" "${ out_file1 }" "${ out_file1.id }" "." "${ input1.dbkey }" "${ species }" "${ input1.metadata.species }" "${ complete_blocks }" "${ remove_gaps }"</command><inputs><param format="maf" name="input1" type="data" label="MAF file to convert"/><param name="species" type="select" label="Select additional species" display="checkboxes" multiple="true" help="The species matching the dbkey of the alignment is always included. A separate history item will be created for each species.">
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