azkaban-developers
Changes
src/java/azkaban/utils/WebUtils.java 159(+78 -81)
src/web/js/azkaban/model/log-data.js 16(+16 -0)
src/web/js/azkaban/model/svg-graph.js 79(+79 -0)
src/web/js/azkaban/util/flow-loader.js 127(+46 -81)
src/web/js/azkaban/view/exflow.js 4(+1 -3)
src/web/js/azkaban/view/flow.js 7(+2 -5)
src/web/js/azkaban/view/job-list.js 4(+4 -0)
src/web/js/azkaban/view/main.js 6(+3 -3)
src/web/js/azkaban/view/svg-graph.js 82(+66 -16)
Details
src/java/azkaban/utils/WebUtils.java 159(+78 -81)
diff --git a/src/java/azkaban/utils/WebUtils.java b/src/java/azkaban/utils/WebUtils.java
index 31322e6..4f65159 100644
--- a/src/java/azkaban/utils/WebUtils.java
+++ b/src/java/azkaban/utils/WebUtils.java
@@ -28,10 +28,10 @@ import azkaban.executor.Status;
public class WebUtils {
public static final String DATE_TIME_STRING = "YYYY-MM-dd HH:mm:ss";
- private static final long ONE_KB = 1024;
- private static final long ONE_MB = 1024 * ONE_KB;
- private static final long ONE_GB = 1024 * ONE_MB;
- private static final long ONE_TB = 1024 * ONE_GB;
+ private static final long ONE_KB = 1024;
+ private static final long ONE_MB = 1024 * ONE_KB;
+ private static final long ONE_GB = 1024 * ONE_MB;
+ private static final long ONE_TB = 1024 * ONE_GB;
public String formatDate(long timeMS) {
if (timeMS == -1) {
@@ -78,79 +78,76 @@ public class WebUtils {
public String formatStatus(Status status) {
switch(status) {
- case SUCCEEDED:
- return "Success";
- case FAILED:
- return "Failed";
- case RUNNING:
- return "Running";
- case DISABLED:
- return "Disabled";
- case KILLED:
- return "Killed";
- case FAILED_FINISHING:
- return "Running w/Failure";
- case PREPARING:
- return "Preparing";
- case READY:
- return "Ready";
- case PAUSED:
- return "Paused";
- case SKIPPED:
- return "Skipped";
- default:
+ case SUCCEEDED:
+ return "Success";
+ case FAILED:
+ return "Failed";
+ case RUNNING:
+ return "Running";
+ case DISABLED:
+ return "Disabled";
+ case KILLED:
+ return "Killed";
+ case FAILED_FINISHING:
+ return "Running w/Failure";
+ case PREPARING:
+ return "Preparing";
+ case READY:
+ return "Ready";
+ case PAUSED:
+ return "Paused";
+ case SKIPPED:
+ return "Skipped";
+ default:
}
-
return "Unknown";
}
- public String formatDateTime(DateTime dt)
- {
+ public String formatDateTime(DateTime dt) {
return DateTimeFormat.forPattern(DATE_TIME_STRING).print(dt);
}
- public String formatDateTime(long timestamp) {
- return formatDateTime(new DateTime(timestamp));
- }
+ public String formatDateTime(long timestamp) {
+ return formatDateTime(new DateTime(timestamp));
+ }
- public String formatPeriod(ReadablePeriod period)
- {
- String periodStr = "null";
+ public String formatPeriod(ReadablePeriod period) {
+ String periodStr = "null";
- if (period == null) {
- return periodStr;
- }
+ if (period == null) {
+ return periodStr;
+ }
- if (period.get(DurationFieldType.years()) > 0) {
- int years = period.get(DurationFieldType.years());
- periodStr = years + " year(s)";
- }
- else if (period.get(DurationFieldType.months()) > 0) {
- int months = period.get(DurationFieldType.months());
- periodStr = months + " month(s)";
- }
- else if (period.get(DurationFieldType.weeks()) > 0) {
- int weeks = period.get(DurationFieldType.weeks());
- periodStr = weeks + " week(s)";
- }
- else if (period.get(DurationFieldType.days()) > 0) {
- int days = period.get(DurationFieldType.days());
- periodStr = days + " day(s)";
- }
- else if (period.get(DurationFieldType.hours()) > 0) {
- int hours = period.get(DurationFieldType.hours());
- periodStr = hours + " hour(s)";
- }
- else if (period.get(DurationFieldType.minutes()) > 0) {
- int minutes = period.get(DurationFieldType.minutes());
- periodStr = minutes + " minute(s)";
- }
- else if (period.get(DurationFieldType.seconds()) > 0) {
- int seconds = period.get(DurationFieldType.seconds());
- periodStr = seconds + " second(s)";
- }
-
- return periodStr;
+ if (period.get(DurationFieldType.years()) > 0) {
+ int years = period.get(DurationFieldType.years());
+ periodStr = years + " year(s)";
+ }
+ else if (period.get(DurationFieldType.months()) > 0) {
+ int months = period.get(DurationFieldType.months());
+ periodStr = months + " month(s)";
+ }
+ else if (period.get(DurationFieldType.weeks()) > 0) {
+ int weeks = period.get(DurationFieldType.weeks());
+ periodStr = weeks + " week(s)";
+ }
+ else if (period.get(DurationFieldType.days()) > 0) {
+ int days = period.get(DurationFieldType.days());
+ periodStr = days + " day(s)";
+ }
+ else if (period.get(DurationFieldType.hours()) > 0) {
+ int hours = period.get(DurationFieldType.hours());
+ periodStr = hours + " hour(s)";
+ }
+ else if (period.get(DurationFieldType.minutes()) > 0) {
+ int minutes = period.get(DurationFieldType.minutes());
+ periodStr = minutes + " minute(s)";
+ }
+ else if (period.get(DurationFieldType.seconds()) > 0) {
+ int seconds = period.get(DurationFieldType.seconds());
+ periodStr = seconds + " second(s)";
+ }
+
+ return periodStr;
}
public String extractNumericalId(String execId) {
@@ -160,18 +157,18 @@ public class WebUtils {
return execId.substring(0, index2);
}
- public String displayBytes(long sizeBytes) {
- NumberFormat nf = NumberFormat.getInstance();
- nf.setMaximumFractionDigits(2);
- if(sizeBytes >= ONE_TB)
- return nf.format(sizeBytes / (double) ONE_TB) + " tb";
- else if(sizeBytes >= ONE_GB)
- return nf.format(sizeBytes / (double) ONE_GB) + " gb";
- else if(sizeBytes >= ONE_MB)
- return nf.format(sizeBytes / (double) ONE_MB) + " mb";
- else if(sizeBytes >= ONE_KB)
- return nf.format(sizeBytes / (double) ONE_KB) + " kb";
- else
- return sizeBytes + " B";
- }
+ public String displayBytes(long sizeBytes) {
+ NumberFormat nf = NumberFormat.getInstance();
+ nf.setMaximumFractionDigits(2);
+ if(sizeBytes >= ONE_TB)
+ return nf.format(sizeBytes / (double) ONE_TB) + " tb";
+ else if(sizeBytes >= ONE_GB)
+ return nf.format(sizeBytes / (double) ONE_GB) + " gb";
+ else if(sizeBytes >= ONE_MB)
+ return nf.format(sizeBytes / (double) ONE_MB) + " mb";
+ else if(sizeBytes >= ONE_KB)
+ return nf.format(sizeBytes / (double) ONE_KB) + " kb";
+ else
+ return sizeBytes + " B";
+ }
}
diff --git a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
index 678c288..5454c99 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
@@ -28,6 +28,9 @@
<script type="text/javascript" src="${context}/js/flowstats.js"></script>
<script type="text/javascript" src="${context}/js/flowstats-no-data.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-execution-list.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-execute-dialog.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-stats.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/exflow.js"></script>
<script type="text/javascript">
var contextURL = "${context}";
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
index ddc9551..cc6940b 100644
--- a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
@@ -32,6 +32,8 @@
<script type="text/javascript" src="${context}/js/flowstats.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/time-graph.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-stats.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-execute-dialog.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/flow.js"></script>
<script type="text/javascript">
var contextURL = "${context}";
diff --git a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
index 631ec0e..cd76ebd 100644
--- a/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/projectpage.vm
@@ -21,9 +21,9 @@
#parse ("azkaban/webapp/servlet/velocity/style.vm")
#parse ("azkaban/webapp/servlet/velocity/javascript.vm")
#parse ("azkaban/webapp/servlet/velocity/svgflowincludes.vm")
- <link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
<script type="text/javascript" src="${context}/js/moment.min.js"></script>
<script type="text/javascript" src="${context}/js/bootstrap-datetimepicker.min.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/flow-execute-dialog.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/project.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/project-modals.js"></script>
<script type="text/javascript">
@@ -37,6 +37,7 @@
var execAccess = ${exec};
var projectName = "$project.name";
</script>
+ <link rel="stylesheet" type="text/css" href="${context}/css/bootstrap-datetimepicker.css" />
</head>
<body>
diff --git a/src/java/azkaban/webapp/servlet/velocity/svgflowincludes.vm b/src/java/azkaban/webapp/servlet/velocity/svgflowincludes.vm
index 773416e..70a3ff6 100644
--- a/src/java/azkaban/webapp/servlet/velocity/svgflowincludes.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/svgflowincludes.vm
@@ -18,21 +18,20 @@
<script type="text/javascript" src="${context}/js/jquery.svganim.min.js"></script>
<script type="text/javascript" src="${context}/js/jquery.svgfilter.min.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/svgutils.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/view/flow-execute.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/flow-loader.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/util/common.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/util/date.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/util/ajax.js"></script>
+
+ <script type="text/javascript" src="${context}/js/azkaban/util/svgutils.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/util/svg-navigate.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/util/layout.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/context-menu.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/ajax.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/util/job-status.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/layout.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/date.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/view/flow-stats.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/view/flow-job.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/view/flow-execution-list.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/util/flow-loader.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/view/job-list.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban/model/svg-graph.js"></script>
<script type="text/javascript" src="${context}/js/azkaban/view/svg-graph.js"></script>
- <script type="text/javascript" src="${context}/js/azkaban/util/svg-navigate.js"></script>
- <link rel="stylesheet" type="text/css" href="${context}/css/azkaban-graph.css" />
\ No newline at end of file
+ <link rel="stylesheet" type="text/css" href="${context}/css/azkaban-graph.css" />
src/web/js/azkaban/model/log-data.js 16(+16 -0)
diff --git a/src/web/js/azkaban/model/log-data.js b/src/web/js/azkaban/model/log-data.js
index 90a958f..958ee5d 100644
--- a/src/web/js/azkaban/model/log-data.js
+++ b/src/web/js/azkaban/model/log-data.js
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2014 LinkedIn Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
$.namespace('azkaban');
azkaban.LogDataModel = Backbone.Model.extend({
src/web/js/azkaban/model/svg-graph.js 79(+79 -0)
diff --git a/src/web/js/azkaban/model/svg-graph.js b/src/web/js/azkaban/model/svg-graph.js
new file mode 100644
index 0000000..c683997
--- /dev/null
+++ b/src/web/js/azkaban/model/svg-graph.js
@@ -0,0 +1,79 @@
+/*
+ * Copyright 2014 LinkedIn Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+$.namespace('azkaban');
+
+azkaban.GraphModel = Backbone.Model.extend({
+ initialize: function() {
+
+ },
+
+ /*
+ * Process and add data from JSON.
+ */
+ addFlow: function(data) {
+ this.processFlowData(data);
+ this.set({'data': data});
+ },
+
+ processFlowData: function(data) {
+ var nodes = {};
+ var edges = new Array();
+
+ // Create a node map
+ for (var i = 0; i < data.nodes.length; ++i) {
+ var node = data.nodes[i];
+ nodes[node.id] = node;
+ if (!node.status) {
+ node.status = "READY";
+ }
+ }
+
+ // Create each node in and out nodes. Create an edge list.
+ for (var i = 0; i < data.nodes.length; ++i) {
+ var node = data.nodes[i];
+ if (node.in) {
+ for (var j = 0; j < node.in.length; ++j) {
+ var fromNode = nodes[node.in[j]];
+ if (!fromNode.outNodes) {
+ fromNode.outNodes = {};
+ }
+ if (!node.inNodes) {
+ node.inNodes = {};
+ }
+
+ fromNode.outNodes[node.id] = node;
+ node.inNodes[fromNode.id] = fromNode;
+ edges.push({to: node.id, from: fromNode.id});
+ }
+ }
+ }
+
+ // Iterate over the nodes again. Parse the data if they're embedded flow data.
+ // Assign each nodes to the parent flow data.
+ for (var key in nodes) {
+ var node = nodes[key];
+ node.parent = data;
+ if (node.type == "flow") {
+ this.processFlowData(node);
+ }
+ }
+
+ // Assign the node map and the edge list
+ data.nodeMap = nodes;
+ data.edges = edges;
+ }
+});
src/web/js/azkaban/util/flow-loader.js 127(+46 -81)
diff --git a/src/web/js/azkaban/util/flow-loader.js b/src/web/js/azkaban/util/flow-loader.js
index 97e447c..ee5ed8b 100644
--- a/src/web/js/azkaban/util/flow-loader.js
+++ b/src/web/js/azkaban/util/flow-loader.js
@@ -1,3 +1,19 @@
+/*
+ * Copyright 2014 LinkedIn Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
var statusStringMap = {
"FAILED": "Failed",
"SUCCEEDED": "Success",
@@ -57,57 +73,6 @@ var createNewPanel = function(node, model, evt) {
backboneView.showExtendedView(evt);
}
-/**
- * Processes the flow data from Javascript
- */
-var processFlowData = function(data) {
- var nodes = {};
- var edges = new Array();
-
- //Create a node map
- for (var i=0; i < data.nodes.length; ++i) {
- var node = data.nodes[i];
- nodes[node.id] = node;
- if (!node.status) {
- node.status = "READY";
- }
- }
-
- // Create each node in and out nodes. Create an edge list.
- for (var i=0; i < data.nodes.length; ++i) {
- var node = data.nodes[i];
- if (node.in) {
- for (var j=0; j < node.in.length; ++j) {
- var fromNode = nodes[node.in[j]];
- if (!fromNode.outNodes) {
- fromNode.outNodes = {};
- }
- if (!node.inNodes) {
- node.inNodes = {};
- }
-
- fromNode.outNodes[node.id] = node;
- node.inNodes[fromNode.id] = fromNode;
- edges.push({to: node.id, from: fromNode.id});
- }
- }
- }
-
- // Iterate over the nodes again. Parse the data if they're embedded flow data.
- // Assign each nodes to the parent flow data.
- for (var key in nodes) {
- var node = nodes[key];
- node.parent = data;
- if (node.type == "flow") {
- processFlowData(node);
- }
- }
-
- // Assign the node map and the edge list
- data.nodeMap = nodes;
- data.edges = edges;
-}
-
var closeAllSubDisplays = function() {
$(".flowExtendedView").hide();
}
@@ -133,25 +98,25 @@ var nodeClickCallback = function(event, model, node) {
}
$.merge(menu, [
- // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
- {break: 1},
- {title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
- {title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
- {break: 1},
- {title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
- {title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
- {break: 1},
- {title: "Center Flow", callback: function() {model.trigger("centerNode", node);}}
+ // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+ {break: 1},
+ {title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
+ {title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
+ {break: 1},
+ {title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
+ {title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
+ {break: 1},
+ {title: "Center Flow", callback: function() {model.trigger("centerNode", node);}}
]);
}
else {
menu = [
- // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
- // {break: 1},
- {title: "Open Job...", callback: function() {window.location.href=requestURL;}},
- {title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
- {break: 1},
- {title: "Center Job", callback: function() {model.trigger("centerNode", node)}}
+ // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+ // {break: 1},
+ {title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+ {title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
+ {break: 1},
+ {title: "Center Job", callback: function() {model.trigger("centerNode", node)}}
];
}
contextMenuView.show(event, menu);
@@ -170,25 +135,25 @@ var jobClickCallback = function(event, model, node) {
if (type == "flow") {
var flowRequestURL = contextURL + "/manager?project=" + projectName + "&flow=" + node.flowId;
menu = [
- // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
- // {break: 1},
- {title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
- {title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
- {break: 1},
- {title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
- {title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
- {break: 1},
- {title: "Center Flow", callback: function() {model.trigger("centerNode", node)}}
+ // {title: "View Properties...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+ // {break: 1},
+ {title: "Open Flow...", callback: function() {window.location.href=flowRequestURL;}},
+ {title: "Open Flow in New Window...", callback: function() {window.open(flowRequestURL);}},
+ {break: 1},
+ {title: "Open Properties...", callback: function() {window.location.href=requestURL;}},
+ {title: "Open Properties in New Window...", callback: function() {window.open(requestURL);}},
+ {break: 1},
+ {title: "Center Flow", callback: function() {model.trigger("centerNode", node)}}
];
}
else {
menu = [
- // {title: "View Job...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
- // {break: 1},
- {title: "Open Job...", callback: function() {window.location.href=requestURL;}},
- {title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
- {break: 1},
- {title: "Center Job", callback: function() {graphModel.trigger("centerNode", node)}}
+ // {title: "View Job...", callback: function() {openJobDisplayCallback(jobId, flowId, event)}},
+ // {break: 1},
+ {title: "Open Job...", callback: function() {window.location.href=requestURL;}},
+ {title: "Open Job in New Window...", callback: function() {window.open(requestURL);}},
+ {break: 1},
+ {title: "Center Job", callback: function() {graphModel.trigger("centerNode", node)}}
];
}
contextMenuView.show(event, menu);
src/web/js/azkaban/view/exflow.js 4(+1 -3)
diff --git a/src/web/js/azkaban/view/exflow.js b/src/web/js/azkaban/view/exflow.js
index eee5a1a..c495584 100644
--- a/src/web/js/azkaban/view/exflow.js
+++ b/src/web/js/azkaban/view/exflow.js
@@ -377,7 +377,6 @@ azkaban.StatsView = Backbone.View.extend({
});
var graphModel;
-azkaban.GraphModel = Backbone.Model.extend({});
var logModel;
azkaban.LogModel = Backbone.Model.extend({});
@@ -582,8 +581,7 @@ $(function() {
var requestData = {"execid": execId, "ajax":"fetchexecflow"};
var successHandler = function(data) {
console.log("data fetched");
- processFlowData(data);
- graphModel.set({data:data});
+ graphModel.addFlow(data);
graphModel.trigger("change:graph");
updateTime = Math.max(updateTime, data.submitTime);
src/web/js/azkaban/view/flow.js 7(+2 -5)
diff --git a/src/web/js/azkaban/view/flow.js b/src/web/js/azkaban/view/flow.js
index 14ee620..32ae40a 100644
--- a/src/web/js/azkaban/view/flow.js
+++ b/src/web/js/azkaban/view/flow.js
@@ -366,7 +366,7 @@ azkaban.SummaryView = Backbone.View.extend({
});
var graphModel;
-azkaban.GraphModel = Backbone.Model.extend({});
+var mainSvgGraphView;
var executionModel;
azkaban.ExecutionModel = Backbone.Model.extend({});
@@ -379,8 +379,6 @@ var flowStatsModel;
var executionsTimeGraphView;
-var mainSvgGraphView;
-
$(function() {
var selected;
// Execution model has to be created before the window switches the tabs.
@@ -452,8 +450,7 @@ $(function() {
};
var successHandler = function(data) {
console.log("data fetched");
- processFlowData(data);
- graphModel.set({data:data});
+ graphModel.addFlow(data);
graphModel.trigger("change:graph");
// Handle the hash changes here so the graph finishes rendering first.
diff --git a/src/web/js/azkaban/view/flow-execution-list.js b/src/web/js/azkaban/view/flow-execution-list.js
index 0ec15a9..5a844a7 100644
--- a/src/web/js/azkaban/view/flow-execution-list.js
+++ b/src/web/js/azkaban/view/flow-execution-list.js
@@ -14,6 +14,10 @@
* the License.
*/
+/*
+ * List of executing jobs on executing flow page.
+ */
+
var executionListView;
azkaban.ExecutionListView = Backbone.View.extend({
events: {
@@ -39,6 +43,7 @@ azkaban.ExecutionListView = Backbone.View.extend({
var flowStartTime = data.startTime;
this.updateProgressBar(data, flowStartTime, flowLastTime);
},
+
//
// handleProgressBoxClick: function(evt) {
// var target = evt.currentTarget;
@@ -61,7 +66,9 @@ azkaban.ExecutionListView = Backbone.View.extend({
updateJobs: function(evt) {
var update = this.model.get("update");
- var lastTime = update.endTime == -1 ? (new Date()).getTime() : update.endTime;
+ var lastTime = update.endTime == -1
+ ? (new Date()).getTime()
+ : update.endTime;
var executingBody = $("#executableBody");
if (update.nodes) {
@@ -69,17 +76,19 @@ azkaban.ExecutionListView = Backbone.View.extend({
}
var data = this.model.get("data");
- var flowLastTime = data.endTime == -1 ? (new Date()).getTime() : data.endTime;
+ var flowLastTime = data.endTime == -1
+ ? (new Date()).getTime()
+ : data.endTime;
var flowStartTime = data.startTime;
this.updateProgressBar(data, flowStartTime, flowLastTime);
},
+
updateJobRow: function(nodes, body) {
if (!nodes) {
return;
}
nodes.sort(function(a,b) { return a.startTime - b.startTime; });
-
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i].changedNode ? nodes[i].changedNode : nodes[i];
@@ -235,6 +244,7 @@ azkaban.ExecutionListView = Backbone.View.extend({
}
}
},
+
toggleExpandFlow: function(flow) {
console.log("Toggle Expand");
var tr = flow.joblistrow;
@@ -256,6 +266,7 @@ azkaban.ExecutionListView = Backbone.View.extend({
$(subFlowRow).show();
}
},
+
addNodeRow: function(node, body) {
var self = this;
var tr = document.createElement("tr");
src/web/js/azkaban/view/main.js 6(+3 -3)
diff --git a/src/web/js/azkaban/view/main.js b/src/web/js/azkaban/view/main.js
index bf5e9a9..2ec3c5b 100644
--- a/src/web/js/azkaban/view/main.js
+++ b/src/web/js/azkaban/view/main.js
@@ -47,14 +47,14 @@ azkaban.ProjectTableView = Backbone.View.extend({
var expander = $(target).children('.project-expander-icon')[0];
$(expander).removeClass('glyphicon-chevron-up');
$(expander).addClass('glyphicon-chevron-down');
- $(targetExpanded).slideUp();
+ $(targetExpanded).slideUp(300);
}
else {
$(target).addClass('collapsed').removeClass('expanded');
var expander = $(target).children('.project-expander-icon')[0];
$(expander).removeClass('glyphicon-chevron-down');
$(expander).addClass('glyphicon-chevron-up');
- $(targetExpanded).slideDown();
+ $(targetExpanded).slideDown(300);
}
}
else {
@@ -78,7 +78,7 @@ azkaban.ProjectTableView = Backbone.View.extend({
var expander = $(target).children('.project-expander-icon')[0];
$(expander).removeClass('glyphicon-chevron-down');
$(expander).addClass('glyphicon-chevron-up');
- $(targetExpanded).slideDown();
+ $(targetExpanded).slideDown(300);
};
$.get(requestURL, request, successHandler, "json");
src/web/js/azkaban/view/svg-graph.js 82(+66 -16)
diff --git a/src/web/js/azkaban/view/svg-graph.js b/src/web/js/azkaban/view/svg-graph.js
index 6910edc..7e0d179 100644
--- a/src/web/js/azkaban/view/svg-graph.js
+++ b/src/web/js/azkaban/view/svg-graph.js
@@ -13,12 +13,17 @@
* License for the specific language governing permissions and limitations under
* the License.
*/
+
+/*
+ * SVG graph view.
+ */
+
$.namespace('azkaban');
azkaban.SvgGraphView = Backbone.View.extend({
events: {
-
},
+
initialize: function(settings) {
this.model.bind('change:selected', this.changeSelected, this);
this.model.bind('centerNode', this.centerNode, this);
@@ -74,6 +79,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.render();
}
},
+
render: function() {
console.log("graph render");
$(this.mainG).empty();
@@ -81,6 +87,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.graphBounds = this.renderGraph(this.model.get("data"), this.mainG);
this.resetPanZoom(0);
},
+
renderGraph: function(data, g) {
g.data = data;
var nodes = data.nodes;
@@ -160,17 +167,25 @@ azkaban.SvgGraphView = Backbone.View.extend({
}
};
- $(".node").each(
- function(d,i){$(this).tooltip({container:self.tooltipcontainer, delay: {show: 500, hide: 100}});
+ $(".node").each(function(d,i) {
+ $(this).tooltip({
+ container: self.tooltipcontainer,
+ delay: {
+ show: 500,
+ hide: 100
+ }
+ });
});
return bounds;
},
+
handleDisabledChange: function(evt) {
this.changeDisabled(this.model.get('data'));
},
+
changeDisabled: function(data) {
- for (var i =0; i < data.nodes.length; ++i) {
+ for (var i = 0; i < data.nodes.length; ++i) {
var node = data.nodes[i];
if (node.disabled) {
if (node.gNode) {
@@ -189,6 +204,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
}
}
},
+
assignInitialStatus: function(evt, data) {
for (var i = 0; i < data.nodes.length; ++i) {
var updateNode = data.nodes[i];
@@ -205,6 +221,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
$(g).attr("title", title);
}
},
+
changeSelected: function(self) {
console.log("change selected");
var selected = this.model.get("selected");
@@ -226,17 +243,20 @@ azkaban.SvgGraphView = Backbone.View.extend({
}
}
},
+
propagateExpansion: function(node) {
if (node.parent.type) {
this.propagateExpansion(node.parent);
this.expandFlow(node.parent);
}
},
+
handleStatusUpdate: function(evt) {
var updateData = this.model.get("update");
var data = this.model.get("data");
this.updateStatusChanges(updateData, data);
},
+
updateStatusChanges: function(updateData, data) {
// Assumes all changes have been applied.
if (updateData.nodes) {
@@ -264,13 +284,14 @@ azkaban.SvgGraphView = Backbone.View.extend({
}
}
},
+
handleRemoveAllStatus: function(gNode) {
for (var j = 0; j < statusList.length; ++j) {
var status = statusList[j];
removeClass(gNode, status);
}
},
-
+
handleRightClick: function(self) {
if (this.rightClick) {
var callbacks = this.rightClick;
@@ -278,7 +299,9 @@ azkaban.SvgGraphView = Backbone.View.extend({
if (callbacks.node && currentTarget.jobid) {
callbacks.node(self, this.model, currentTarget.nodeobj);
}
- else if (callbacks.edge && (currentTarget.nodeName == "polyline" || currentTarget.nodeName == "line")) {
+ else if (callbacks.edge &&
+ (currentTarget.nodeName == "polyline" ||
+ currentTarget.nodeName == "line")) {
callbacks.edge(self, this.model);
}
else if (callbacks.graph) {
@@ -286,9 +309,9 @@ azkaban.SvgGraphView = Backbone.View.extend({
}
return false;
}
-
return true;
- },
+ },
+
drawEdge: function(self, edge, g) {
var svg = this.svg;
var svgns = self.svgns;
@@ -318,6 +341,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
edge.line.data = edge;
}
},
+
drawNode: function(self, node, g) {
if (node.type == 'flow') {
this.drawFlowNode(self, node, g);
@@ -326,6 +350,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.drawBoxNode(self, node, g);
}
},
+
moveNodes: function(nodes) {
var svg = this.svg;
for (var i = 0; i < nodes.length; ++i) {
@@ -335,6 +360,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
svg.change(gNode, {"transform": translateStr(node.x, node.y)});
}
},
+
expandFlow: function(node) {
var svg = this.svg;
var gnode = node.gNode;
@@ -376,6 +402,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
bounds.maxY = bounds.maxY ? bounds.maxY + margin : margin;
this.graphBounds = bounds;
},
+
collapseFlow: function(node) {
console.log("Collapsing flow");
var svg = this.svg;
@@ -403,8 +430,8 @@ azkaban.SvgGraphView = Backbone.View.extend({
bounds.maxX = bounds.maxX ? bounds.maxX + margin : margin;
bounds.maxY = bounds.maxY ? bounds.maxY + margin : margin;
this.graphBounds = bounds;
-
},
+
relayoutFlow: function(node) {
if (node.expanded) {
this.layoutExpandedFlowNode(node);
@@ -419,9 +446,9 @@ azkaban.SvgGraphView = Backbone.View.extend({
this.animateExpandedFlowNode(node, 250);
}
},
+
moveNodeEdges: function(nodes, edges) {
var svg = this.svg;
-
for (var i = 0; i < nodes.length; ++i) {
var node = nodes[i];
var gNode = node.gNode;
@@ -452,11 +479,16 @@ azkaban.SvgGraphView = Backbone.View.extend({
edge.oldpoints = pointArray;
}
else {
- $(line).animate({svgX1: startNode.x, svgY1: startPointY, svgX2: endNode.x, svgY2: endPointY});
+ $(line).animate({
+ svgX1: startNode.x,
+ svgY1: startPointY,
+ svgX2: endNode.x,
+ svgY2: endPointY
+ });
}
}
-
},
+
calculateBounds: function(nodes) {
var bounds = {};
var node = nodes[0];
@@ -485,6 +517,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
return bounds;
},
+
drawBoxNode: function(self, node, g) {
var svg = this.svg;
var horizontalMargin = 8;
@@ -511,6 +544,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
node.gNode = nodeG;
nodeG.data = node;
},
+
drawFlowNode: function(self, node, g) {
var svg = this.svg;
@@ -529,7 +563,9 @@ azkaban.SvgGraphView = Backbone.View.extend({
var jobNameText = svg.text(labelG, textOffset, 1, node.label);
var flowIdText = svg.text(labelG, textOffset, 11, node.flowId, {"font-size": 8})
var tempLabelG = labelG.getBBox();
- var iconImage = svg.image(labelG, 0, -iconHeight/2, iconWidth, iconHeight, contextURL + "/images/graph-icon.png", {});
+ var iconImage = svg.image(
+ labelG, 0, -iconHeight/2, iconWidth, iconHeight,
+ contextURL + "/images/graph-icon.png", {});
// Assign key values to make searching quicker
node.gNode=nodeG;
@@ -543,6 +579,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
// Layout everything in the node
this.layoutFlowNode(self, node);
},
+
layoutFlowNode: function(self, node) {
var svg = this.svg;
var horizontalMargin = 8;
@@ -566,6 +603,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
node.collapsedHeight = totalHeight;
node.collapsedWidth = totalWidth;
},
+
layoutExpandedFlowNode: function(node) {
var svg = this.svg;
var topmargin= 30, bottommargin=5;
@@ -585,6 +623,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
//$(innerG).animate({svgTransform: translateStr(-node.width/2, -node.height/2)}, 50);
//$(borderRect).animate({svgWidth: node.width, svgHeight: node.height}, 50);
},
+
animateExpandedFlowNode: function(node, time) {
var gNode = node.gNode;
var innerG = gNode.innerG;
@@ -594,26 +633,36 @@ azkaban.SvgGraphView = Backbone.View.extend({
$(borderRect).animate({svgWidth: node.width, svgHeight: node.height}, time);
$(borderRect).animate({svgFill: 'white'}, time);
},
+
resetPanZoom: function(duration) {
var bounds = this.graphBounds;
- var param = {x: bounds.minX, y: bounds.minY, width: (bounds.maxX - bounds.minX), height: (bounds.maxY - bounds.minY), duration: duration };
+ var param = {
+ x: bounds.minX,
+ y: bounds.minY,
+ width: (bounds.maxX - bounds.minX),
+ height: (bounds.maxY - bounds.minY), duration: duration
+ };
this.panZoom(param);
},
+
centerNode: function(node) {
// The magic of affine transformation.
- // Multiply the inverse root matrix with the current matrix to get the node position.
+ // Multiply the inverse root matrix with the current matrix to get the node
+ // position.
// Rather do this than to traverse backwards through the scene graph.
var ctm = node.gNode.getCTM();
var transform = node.gNode.getTransformToElement();
var globalCTM = this.mainG.getCTM().inverse();
var otherTransform = globalCTM.multiply(ctm);
- // Also a beauty of affine transformation. The translate is always the left most column of the matrix.
+ // Also a beauty of affine transformation. The translate is always the
+ // left most column of the matrix.
var x = otherTransform.e - node.width/2;
var y = otherTransform.f - node.height/2;
this.panZoom({x: x, y: y, width: node.width, height: node.height});
},
+
globalNodePosition: function(gNode) {
if (node.parent) {
@@ -624,6 +673,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
return {x: node.x, y: node.y};
}
},
+
panZoom: function(params) {
params.maxScale = 2;
$(this.svgGraph).svgNavigate("transformToBox", params);