Details
diff --git a/azkaban-web-server/src/web/js/azkaban/util/flow-loader.js b/azkaban-web-server/src/web/js/azkaban/util/flow-loader.js
index b260fca..9a128bc 100644
--- a/azkaban-web-server/src/web/js/azkaban/util/flow-loader.js
+++ b/azkaban-web-server/src/web/js/azkaban/util/flow-loader.js
@@ -81,18 +81,34 @@ var nodeClickCallback = function (event, model, node) {
var flowRequestURL = contextURL + "/manager?project=" + projectName
+ "&flow=" + node.flowId;
if (node.expanded) {
- menu = [{
- title: "Collapse Flow...", callback: function () {
- model.trigger("collapseFlow", node);
+ menu = [
+ {
+ title: "Collapse Flow...", callback: function () {
+ model.trigger("collapseFlow", node);
+ }
+ },
+ {
+ title: "Collapse All Flows...", callback: function () {
+ model.trigger("collapseAllFlows", node);
+ model.trigger("resetPanZoom");
+ }
}
- }];
+ ];
}
else {
- menu = [{
- title: "Expand Flow...", callback: function () {
- model.trigger("expandFlow", node);
+ menu = [
+ {
+ title: "Expand Flow...", callback: function () {
+ model.trigger("expandFlow", node);
+ }
+ },
+ {
+ title: "Expand All Flows...", callback: function () {
+ model.trigger("expandAllFlows", node);
+ model.trigger("resetPanZoom");
+ }
}
- }];
+ ];
}
$.merge(menu, [
@@ -100,30 +116,30 @@ var nodeClickCallback = function (event, model, node) {
{break: 1},
{
title: "Open Flow...", callback: function () {
- window.location.href = flowRequestURL;
- }
+ window.location.href = flowRequestURL;
+ }
},
{
title: "Open Flow in New Window...", callback: function () {
- window.open(flowRequestURL);
- }
+ window.open(flowRequestURL);
+ }
},
{break: 1},
{
title: "Open Properties...", callback: function () {
- window.location.href = requestURL;
- }
+ window.location.href = requestURL;
+ }
},
{
title: "Open Properties in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Center Flow", callback: function () {
- model.trigger("centerNode", node);
- }
+ model.trigger("centerNode", node);
+ }
}
]);
}
@@ -133,19 +149,19 @@ var nodeClickCallback = function (event, model, node) {
// {break: 1},
{
title: "Open Job...", callback: function () {
- window.location.href = requestURL;
- }
+ window.location.href = requestURL;
+ }
},
{
title: "Open Job in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Center Job", callback: function () {
- model.trigger("centerNode", node)
- }
+ model.trigger("centerNode", node)
+ }
}
];
}
@@ -171,30 +187,30 @@ var jobClickCallback = function (event, model, node) {
// {break: 1},
{
title: "Open Flow...", callback: function () {
- window.location.href = flowRequestURL;
- }
+ window.location.href = flowRequestURL;
+ }
},
{
title: "Open Flow in New Window...", callback: function () {
- window.open(flowRequestURL);
- }
+ window.open(flowRequestURL);
+ }
},
{break: 1},
{
title: "Open Properties...", callback: function () {
- window.location.href = requestURL;
- }
+ window.location.href = requestURL;
+ }
},
{
title: "Open Properties in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Center Flow", callback: function () {
- model.trigger("centerNode", node)
- }
+ model.trigger("centerNode", node)
+ }
}
];
}
@@ -204,19 +220,19 @@ var jobClickCallback = function (event, model, node) {
// {break: 1},
{
title: "Open Job...", callback: function () {
- window.location.href = requestURL;
- }
+ window.location.href = requestURL;
+ }
},
{
title: "Open Job in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Center Job", callback: function () {
- graphModel.trigger("centerNode", node)
- }
+ graphModel.trigger("centerNode", node)
+ }
}
];
}
@@ -236,20 +252,33 @@ var graphClickCallback = function (event, model) {
var menu = [
{
+ title: "Expand All Flows...", callback: function () {
+ model.trigger("expandAllFlows");
+ model.trigger("resetPanZoom");
+ }
+ },
+ {
+ title: "Collapse All Flows...", callback: function () {
+ model.trigger("collapseAllFlows");
+ model.trigger("resetPanZoom");
+ }
+ },
+ {break: 1},
+ {
title: "Open Flow...", callback: function () {
- window.location.href = requestURL;
- }
+ window.location.href = requestURL;
+ }
},
{
title: "Open Flow in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Center Graph", callback: function () {
- model.trigger("resetPanZoom");
- }
+ model.trigger("resetPanZoom");
+ }
}
];
diff --git a/azkaban-web-server/src/web/js/azkaban/view/flow-execute-dialog.js b/azkaban-web-server/src/web/js/azkaban/view/flow-execute-dialog.js
index 1175ee5..31dd5df 100644
--- a/azkaban-web-server/src/web/js/azkaban/view/flow-execute-dialog.js
+++ b/azkaban-web-server/src/web/js/azkaban/view/flow-execute-dialog.js
@@ -374,8 +374,9 @@ azkaban.EditTableView = Backbone.View.extend({
},
handleEditColumn: function (evt) {
- if (evt.target.tagName == "INPUT")
+ if (evt.target.tagName == "INPUT") {
return;
+ }
var curTarget = evt.currentTarget;
var text = $(curTarget).children(".spanValue").text();
@@ -636,13 +637,19 @@ var expanelNodeClickCallback = function (event, model, node) {
menu = [
{
title: "Collapse Flow...", callback: function () {
- model.trigger("collapseFlow", node);
- }
+ model.trigger("collapseFlow", node);
+ }
+ },
+ {
+ title: "Collapse All Flows...", callback: function () {
+ model.trigger("collapseAllFlows", node);
+ model.trigger("resetPanZoom");
+ }
},
{
title: "Open Flow in New Window...", callback: function () {
- window.open(flowRequestURL);
- }
+ window.open(flowRequestURL);
+ }
}
];
@@ -651,13 +658,19 @@ var expanelNodeClickCallback = function (event, model, node) {
menu = [
{
title: "Expand Flow...", callback: function () {
- model.trigger("expandFlow", node);
- }
+ model.trigger("expandFlow", node);
+ }
+ },
+ {
+ title: "Expand All Flows...", callback: function () {
+ model.trigger("expandAllFlows", node);
+ model.trigger("resetPanZoom");
+ }
},
{
title: "Open Flow in New Window...", callback: function () {
- window.open(flowRequestURL);
- }
+ window.open(flowRequestURL);
+ }
}
];
}
@@ -668,8 +681,8 @@ var expanelNodeClickCallback = function (event, model, node) {
menu = [
{
title: "Open Job in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
];
}
@@ -678,70 +691,70 @@ var expanelNodeClickCallback = function (event, model, node) {
{break: 1},
{
title: "Enable", callback: function () {
- touchNode(node, false);
- }, submenu: [
- {
- title: "Parents", callback: function () {
- touchParents(node, false);
- }
- },
- {
- title: "Ancestors", callback: function () {
- touchAncestors(node, false);
- }
- },
- {
- title: "Children", callback: function () {
- touchChildren(node, false);
- }
- },
- {
- title: "Descendents", callback: function () {
- touchDescendents(node, false);
- }
- },
- {
- title: "Enable All", callback: function () {
- enableAll();
- }
- }
- ]
+ touchNode(node, false);
+ }, submenu: [
+ {
+ title: "Parents", callback: function () {
+ touchParents(node, false);
+ }
+ },
+ {
+ title: "Ancestors", callback: function () {
+ touchAncestors(node, false);
+ }
+ },
+ {
+ title: "Children", callback: function () {
+ touchChildren(node, false);
+ }
+ },
+ {
+ title: "Descendents", callback: function () {
+ touchDescendents(node, false);
+ }
+ },
+ {
+ title: "Enable All", callback: function () {
+ enableAll();
+ }
+ }
+ ]
},
{
title: "Disable", callback: function () {
- touchNode(node, true)
- }, submenu: [
- {
- title: "Parents", callback: function () {
- touchParents(node, true);
- }
- },
- {
- title: "Ancestors", callback: function () {
- touchAncestors(node, true);
- }
- },
- {
- title: "Children", callback: function () {
- touchChildren(node, true);
- }
- },
- {
- title: "Descendents", callback: function () {
- touchDescendents(node, true);
- }
- },
- {
- title: "Disable All", callback: function () {
- disableAll();
- }
- }
- ]
+ touchNode(node, true)
+ }, submenu: [
+ {
+ title: "Parents", callback: function () {
+ touchParents(node, true);
+ }
+ },
+ {
+ title: "Ancestors", callback: function () {
+ touchAncestors(node, true);
+ }
+ },
+ {
+ title: "Children", callback: function () {
+ touchChildren(node, true);
+ }
+ },
+ {
+ title: "Descendents", callback: function () {
+ touchDescendents(node, true);
+ }
+ },
+ {
+ title: "Disable All", callback: function () {
+ disableAll();
+ }
+ }
+ ]
},
{
title: "Center Job", callback: function () {
- model.trigger("centerNode", node);
- }
+ model.trigger("centerNode", node);
+ }
}
]);
@@ -760,26 +773,38 @@ var expanelGraphClickCallback = function (event) {
var menu = [
{
+ title: "Expand All Flows...", callback: function () {
+ executableGraphModel.trigger("expandAllFlows");
+ executableGraphModel.trigger("resetPanZoom");
+ }
+ },
+ {
+ title: "Collapse All Flows...", callback: function () {
+ executableGraphModel.trigger("collapseAllFlows");
+ executableGraphModel.trigger("resetPanZoom");
+ }
+ },
+ {
title: "Open Flow in New Window...", callback: function () {
- window.open(requestURL);
- }
+ window.open(requestURL);
+ }
},
{break: 1},
{
title: "Enable All", callback: function () {
- enableAll();
- }
+ enableAll();
+ }
},
{
title: "Disable All", callback: function () {
- disableAll();
- }
+ disableAll();
+ }
},
{break: 1},
{
title: "Center Graph", callback: function () {
- executableGraphModel.trigger("resetPanZoom");
- }
+ executableGraphModel.trigger("resetPanZoom");
+ }
}
];
diff --git a/azkaban-web-server/src/web/js/azkaban/view/svg-graph.js b/azkaban-web-server/src/web/js/azkaban/view/svg-graph.js
index 12d7c50..250b134 100644
--- a/azkaban-web-server/src/web/js/azkaban/view/svg-graph.js
+++ b/azkaban-web-server/src/web/js/azkaban/view/svg-graph.js
@@ -33,6 +33,8 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.model.bind('change:updateAll', this.handleUpdateAllStatus, this);
this.model.bind('expandFlow', this.expandFlow, this);
this.model.bind('collapseFlow', this.collapseFlow, this);
+ this.model.bind('expandAllFlows', this.expandAllFlows, this);
+ this.model.bind('collapseAllFlows', this.collapseAllFlows, this);
this.graphMargin = settings.graphMargin ? settings.graphMargin : 25;
this.svgns = "http://www.w3.org/2000/svg";
@@ -81,7 +83,6 @@ azkaban.SvgGraphView = Backbone.View.extend({
},
render: function () {
- console.log("graph render");
$(this.mainG).empty();
this.graphBounds = this.renderGraph(this.model.get("data"), this.mainG);
@@ -439,6 +440,46 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.graphBounds = bounds;
},
+ expandAllFlows: function (node) {
+ if (node) {
+ // expands all embedded flows inside given node
+ if (node.type == 'flow') {
+ this.expandFlow(node);
+
+ for (var i = 0; i < node.nodes.length; ++i) {
+ this.expandAllFlows(node.nodes[i]);
+ }
+ }
+ } else {
+ // expands all embedded flows in the graph
+ var nodes = this.model.get("data").nodes;
+ for (var i = 0; i < nodes.length; ++i) {
+ this.expandAllFlows(nodes[i]);
+ }
+ }
+ },
+
+ collapseAllFlows: function (node) {
+ if (node) {
+ // collapse all embedded flows inside given node
+
+ // collapse already rendered nodes of type flow
+ if (node.type == 'flow' && node.gNode) {
+ this.collapseFlow(node);
+
+ for (var i = 0; i < node.nodes.length; ++i) {
+ this.collapseAllFlows(node.nodes[i]);
+ }
+ }
+ } else {
+ // collapse all embedded flows in the graph
+ var nodes = this.model.get("data").nodes;
+ for (var i = 0; i < nodes.length; ++i) {
+ this.collapseAllFlows(nodes[i]);
+ }
+ }
+ },
+
relayoutFlow: function (node) {
if (node.expanded) {
this.layoutExpandedFlowNode(node);