azkaban-aplcache
Changes
src/web/css/azkaban.css 141(+121 -20)
src/web/css/images/addIcon.png 0(+0 -0)
src/web/css/images/removeIcon.png 0(+0 -0)
src/web/js/azkaban.exflow.options.view.js 138(+138 -0)
src/web/js/azkaban.exflow.view.js 453(+0 -453)
src/web/js/azkaban.flow.graph.view.js 266(+266 -0)
src/web/js/azkaban.flow.job.view.js 189(+189 -0)
src/web/js/azkaban.flow.view.js 228(+3 -225)
src/web/js/azkaban.job.status.utils.js 39(+39 -0)
src/web/js/svgNavigate.js 8(+7 -1)
Details
diff --git a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
index e89c6f9..ebc33f5 100644
--- a/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/executingflowpage.vm
@@ -11,8 +11,11 @@
<script type="text/javascript" src="${context}/js/jquery.simplemodal.js"></script>
<script type="text/javascript" src="${context}/js/jquery.contextMenu.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.job.status.utils.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.layout.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.flow.job.view.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.flow.graph.view.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.exflow.view.js"></script>
<script type="text/javascript" src="${context}/js/svgNavigate.js"></script>
<script type="text/javascript">
@@ -69,13 +72,13 @@
</div>
<div id="graphView">
<div class="relative">
- <div id="jobList">
- <div id="filterList">
- <input id="filter" placeholder=" Job Filter" />
+ <div id="jobList" class="jobList">
+ <div id="filterList" class="filterList">
+ <input id="filter" class="filter" placeholder=" Job Filter" />
</div>
- <div id="list">
+ <div id="list" class="list">
</div>
- <div id="resetPanZoomBtn" class="btn5" >Reset Pan Zoom</div>
+ <div id="resetPanZoomBtn" class="btn5 resetPanZoomBtn" >Reset Pan Zoom</div>
</div>
<div id="svgDiv" >
<svg id="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
index 96aaedf..f8096c1 100644
--- a/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/flowpage.vm
@@ -14,7 +14,10 @@
<script type="text/javascript" src="${context}/js/azkaban.ajax.utils.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.nav.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.layout.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.flow.job.view.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.flow.graph.view.js"></script>
<script type="text/javascript" src="${context}/js/azkaban.flow.view.js"></script>
+ <script type="text/javascript" src="${context}/js/azkaban.exflow.options.view.js"></script>
<script type="text/javascript" src="${context}/js/svgNavigate.js"></script>
<script type="text/javascript">
var contextURL = "${context}";
@@ -54,7 +57,7 @@
<h4><a href="${context}/manager?project=${project.name}">Project <span>$project.name</span></a></h4>
</div>
- <div id="executebtn" class="btn1">Execute...</div>
+ <div id="executebtn" class="btn1">Execute</div>
<div id="scheduleflowbtn" class="btn2 scheduleflow">Schedule Flow</div>
</div>
@@ -67,16 +70,16 @@
</div>
<div id="graphView">
<div class="relative">
- <div id="jobList">
- <div id="filterList">
- <input id="filter" placeholder=" Job Filter" />
+ <div id="jobList" class="jobList">
+ <div id="filterList" class="filterList">
+ <input id="filter" class="filter" placeholder=" Job Filter" />
</div>
- <div id="list">
+ <div id="list" class="list">
</div>
- <div id="resetPanZoomBtn" class="btn5" >Reset Pan Zoom</div>
+ <div id="resetPanZoomBtn" class="btn5 resetPanZoomBtn" >Reset Pan Zoom</div>
</div>
- <div id="svgDiv" >
- <svg id="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
+ <div id="svgDiv" class="svgDiv">
+ <svg id="svgGraph" class="svgGraph" xmlns="http://www.w3.org/2000/svg" version="1.1" shape-rendering="optimize-speed" text-rendering="optimize-speed" >
</svg>
</div>
</div>
@@ -189,17 +192,59 @@
<div id="modalBackground" class="modalBackground2">
<div id="executing-options" class="modal modalContainer2">
<a href='#' title='Close' class='modal-close'>x</a>
- <h3>Executing Flow</h3>
+ <h3>Executing Flow Options</h3>
<div>
<ul class="optionsPicker">
- <li>General Options</li>
- <li>Flow Options</li>
+ <li id="generalOptions">General Options</li>
+ <li id="flowOptions">Flow Options</li>
</ul>
</div>
<div class="optionsPane">
- <div class="generalPanel panel">
+ <div id="generalPanel" class="generalPanel panel">
+ <div>
+ <h4>Completion Actions</h4>
+ <dl>
+ <dt>Failure Action</dt>
+ <dd>
+ <select name="failureAction">
+ <option value="finishCurrent">Finish Current</option>
+ <option value="cancelImmediately">Cancel All</option>
+ <option value="finishPossible">Finish All Possible</option>
+ </select>
+ </dd>
+ <dt>Failure Email</dt>
+ <dd>
+ <textarea></textarea>
+ </dd>
+ <dt>Notify on Failure</dt>
+ <dd>
+ <input class="checkbox" type="checkbox" name="notify" value="first" checked >First Failure</input>
+ <input class="checkbox" type="checkbox" name="notify" value="last">Flow Stop</input>
+ </dd>
+ <dt>Success Email</dt>
+ <dd>
+ <textarea></textarea>
+ </dd>
+ </dl>
+ </div>
+ <div id="flowPropertyOverride">
+ <h4>Flow Property Override</h4>
+ <div class="tableDiv">
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ <tr id="addRow"><td id="addRow-col" colspan="2"><span class="addIcon"></span><a href="#">Add Row</a></td></tr>
+ </tbody>
+ </table>
+ </div>
+ </div>
</div>
- <div class="graphPanel panel">
+ <div id="graphPanel" class="graphPanel panel">
<div class="jobList">
<div id="filterList2">
<input id="filter2" placeholder=" Job Filter" />
src/web/css/azkaban.css 141(+121 -20)
diff --git a/src/web/css/azkaban.css b/src/web/css/azkaban.css
index 45425e5..2d3fdb1 100644
--- a/src/web/css/azkaban.css
+++ b/src/web/css/azkaban.css
@@ -1344,6 +1344,15 @@ tr:hover td {
color: #CCC;
}
+#executing-options ul.optionsPicker li.selected {
+ text-decoration: underline;
+ color: #000;
+}
+
+#executing-options ul.optionsPicker li.selected:hover {
+ color: #000;
+}
+
#executing-options ul.optionsPicker li:hover {
color: #888;
}
@@ -1351,7 +1360,7 @@ tr:hover td {
#executing-options .optionsPane {
position: absolute;
top: 85px;
- background-color: #000;
+ background-color: #FFF;
left: 0px;
right: 0px;
bottom: 0px;
@@ -1361,11 +1370,103 @@ tr:hover td {
position: absolute;
width: 100%;
top: 0px;
- bottom: 60px;
+ bottom: 65px;
}
#executing-options .generalPanel.panel {
- background-color: #ACC;
+ background-color: #F4F4F4;
+ padding-top: 15px;
+}
+
+#executing-options h3 {
+ margin-left: 20px;
+ font-size: 14pt;
+ border-bottom: 1px solid #CCC;
+}
+
+#executing-options h4 {
+ margin-left: 20px;
+ font-size: 12pt;
+ border-bottom: 1px solid #CCC;
+}
+
+#generalPanel {
+ overflow: auto;
+}
+
+#generalPanel dt {
+ width: 150px;
+ font-size: 10pt;
+ font-weight: bold;
+ margin-top: 5px;
+}
+
+#generalPanel textarea {
+ width: 500px;
+}
+
+#generalPanel table #addRow {
+ cursor: pointer;
+}
+
+#generalPanel table tr {
+ height: 24px;
+}
+
+#generalPanel table .editable {
+
+}
+
+#generalPanel table .editable input {
+ border: 1px solid #009FC9;
+ height: 16px;
+}
+
+#generalPanel table .name {
+ width: 40%;
+}
+
+#generalPanel span.addIcon {
+ display: block;
+ width: 16px;
+ height: 16px;
+ background-image: url("./images/addIcon.png");
+}
+
+#generalPanel span.removeIcon {
+ display: block;
+ visibility:hidden;
+ disabled: true;
+ width: 16px;
+ height: 16px;
+ background-image: url("./images/removeIcon.png");
+ cursor: pointer;
+}
+
+#generalPanel .editable:hover span.removeIcon {
+ visibility:visible;
+}
+
+#generalPanel {
+}
+
+#generalPanel span {
+ float: left;
+ margin-left: 5px;
+}
+
+#generalPanel dd {
+ font-size: 10pt;
+}
+
+#flowPropertyOverride {
+ clear: both;
+ padding-top: 30px;
+}
+
+#flowPropertyOverride .tableDiv {
+ padding-right: 20px;
+ padding-left: 20px;
}
#jobList {
@@ -1389,7 +1490,7 @@ tr:hover td {
bottom: 120px;
}
-#resetPanZoomBtn {
+.resetPanZoomBtn {
position: absolute;
bottom: 90px;
}
@@ -1407,74 +1508,74 @@ tr:hover td {
top: 100px;
}
-#filter {
+.filter {
width: 100%;
}
-#list ul {
+.list ul {
white-space: nowrap
}
-#list ul li {
+.list ul li {
margin: 4px 5px;
border-bottom: 1px solid #EEE;
cursor: pointer;
background-position: 16px 0px;
}
-#list ul li:hover{
+.list ul li:hover{
background-color: #E1E3E2;
color: #009FC9;
}
-#list ul li.selected {
+.list ul li.selected {
background-color: #009FC9;
color: #EEE;
}
-#list ul li.nodedisabled {
+.list ul li.nodedisabled {
opacity: 0.3;
}
-#list ul li.DISABLED {
+.list ul li.DISABLED {
opacity: 0.3;
}
-#list ul li.DISABLED .icon {
+.list ul li.DISABLED .icon {
background-position: 16px 0px;
}
-#list ul li.READY .icon {
+.list ul li.READY .icon {
background-position: 16px 0px;
}
-#list ul li.RUNNING .icon {
+.list ul li.RUNNING .icon {
background-position: 32px 0px;
}
-#list ul li.SUCCEEDED .icon {
+.list ul li.SUCCEEDED .icon {
background-position: 48px 0px;
}
-#list ul li.FAILED .icon {
+.list ul li.FAILED .icon {
background-position: 0px 0px;
}
-#list ul li.KILLED .icon {
+.list ul li.KILLED .icon {
background-position: 0px 0px;
}
-#list ul li a {
+.list ul li a {
font-size: 10pt;
margin-left: 5px;
}
-#list ul li a span {
+.list ul li a span {
background-color: #FF0;
color: black;
}
-#list ul li .icon {
+.list ul li .icon {
float: left;
width: 16px;
height: 16px;
src/web/css/images/addIcon.png 0(+0 -0)
diff --git a/src/web/css/images/addIcon.png b/src/web/css/images/addIcon.png
new file mode 100644
index 0000000..f079305
Binary files /dev/null and b/src/web/css/images/addIcon.png differ
src/web/css/images/removeIcon.png 0(+0 -0)
diff --git a/src/web/css/images/removeIcon.png b/src/web/css/images/removeIcon.png
new file mode 100644
index 0000000..32132da
Binary files /dev/null and b/src/web/css/images/removeIcon.png differ
src/web/js/azkaban.exflow.options.view.js 138(+138 -0)
diff --git a/src/web/js/azkaban.exflow.options.view.js b/src/web/js/azkaban.exflow.options.view.js
new file mode 100644
index 0000000..1c19104
--- /dev/null
+++ b/src/web/js/azkaban.exflow.options.view.js
@@ -0,0 +1,138 @@
+var executeFlowView;
+azkaban.ExecuteFlowView = Backbone.View.extend({
+ events : {
+ "click" : "closeEditingTarget",
+ "click #execute-btn": "handleExecuteFlow",
+ "click #execute-custom-btn": "handleCustomFlow",
+ "click #cancel-btn": "handleCancelExecution",
+ "click .modal-close": "handleCancelExecution",
+ "click #generalOptions": "handleGeneralOptionsSelect",
+ "click #flowOptions": "handleFlowOptionsSelect",
+ "click #addRow": "handleAddRow",
+ "click table .editable": "handleEditColumn",
+ "click table .removeIcon": "handleRemoveColumn"
+ },
+ initialize: function(evt) {
+ $('#executebtn').click( function() {
+ $('#modalBackground').show();
+ $('#executing-options').show();
+ });
+
+ this.handleGeneralOptionsSelect();
+ },
+ handleCancelExecution: function(evt) {
+ var executeURL = contextURL + "/executor";
+ $('#modalBackground').hide();
+ $('#executing-options').hide();
+ },
+ handleGeneralOptionsSelect: function(evt) {
+ $('#flowOptions').removeClass('selected');
+ $('#generalOptions').addClass('selected');
+
+ $('#generalPanel').show();
+ $('#graphPanel').hide();
+ },
+ handleFlowOptionsSelect: function(evt) {
+ $('#generalOptions').removeClass('selected');
+ $('#flowOptions').addClass('selected');
+
+ $('#graphPanel').show();
+ $('#generalPanel').hide();
+ },
+ handleExecuteFlow: function(evt) {
+ var executeURL = contextURL + "/executor";
+ $.get(
+ executeURL,
+ {"project": projectName, "ajax":"executeFlow", "flow":flowName, "disabled":graphModel.get("disabled")},
+ function(data) {
+ if (data.error) {
+ alert(data.error);
+ }
+ else {
+ var redirectURL = contextURL + "/executor?execid=" + data.execid;
+ window.location.href = redirectURL;
+ }
+ },
+ "json"
+ );
+ },
+ handleCustomFlow: function(evt) {
+
+ },
+ handleAddRow: function(evt) {
+ var tr = document.createElement("tr");
+ var tdName = document.createElement("td");
+ var tdValue = document.createElement("td");
+
+ var icon = document.createElement("span");
+ $(icon).addClass("removeIcon");
+ var nameData = document.createElement("span");
+ $(nameData).addClass("spanValue");
+ var valueData = document.createElement("span");
+ $(valueData).addClass("spanValue");
+
+ $(tdName).append(icon);
+ $(tdName).append(nameData);
+ $(tdName).addClass("name");
+ $(tdName).addClass("editable");
+
+ $(tdValue).append(valueData);
+ $(tdValue).addClass("editable");
+
+ $(tr).append(tdName);
+ $(tr).append(tdValue);
+
+ $(tr).insertBefore("#addRow");
+ },
+ handleEditColumn : function(evt) {
+ var curTarget = evt.currentTarget;
+
+ if (this.editingTarget != curTarget) {
+ this.closeEditingTarget();
+
+ var text = $(curTarget).children(".spanValue").text();
+ $(curTarget).empty();
+
+ var input = document.createElement("input");
+ $(input).attr("type", "text");
+ $(input).css("width", "100%");
+ $(input).val(text);
+ $(curTarget).addClass("editing");
+ $(curTarget).append(input);
+ $(input).focus();
+ this.editingTarget = curTarget;
+ }
+ },
+ handleRemoveColumn : function(evt) {
+ var curTarget = evt.currentTarget;
+ // Should be the table
+ var row = curTarget.parentElement.parentElement;
+ $(row).remove();
+ },
+ handleResetData : function(evt) {
+ },
+ closeEditingTarget: function(evt) {
+ if (this.editingTarget != null && this.editingTarget != evt.target && this.editingTarget != evt.target.parentElement ) {
+ var input = $(this.editingTarget).children("input")[0];
+ var text = $(input).val();
+ $(input).remove();
+
+ var valueData = document.createElement("span");
+ $(valueData).addClass("spanValue");
+ $(valueData).text(text);
+
+ if ($(this.editingTarget).hasClass("name")) {
+ var icon = document.createElement("span");
+ $(icon).addClass("removeIcon");
+ $(this.editingTarget).append(icon);
+ }
+
+ $(this.editingTarget).removeClass("editing");
+ $(this.editingTarget).append(valueData);
+ this.editingTarget = null;
+ }
+ },
+ addRowData : function(evt) {
+
+ }
+});
\ No newline at end of file
src/web/js/azkaban.exflow.view.js 453(+0 -453)
diff --git a/src/web/js/azkaban.exflow.view.js b/src/web/js/azkaban.exflow.view.js
index dbbaeb1..ff1cb39 100644
--- a/src/web/js/azkaban.exflow.view.js
+++ b/src/web/js/azkaban.exflow.view.js
@@ -1,19 +1,5 @@
$.namespace('azkaban');
-var statusList = ["FAILED", "FAILED_FINISHING", "SUCCEEDED", "RUNNING", "WAITING", "KILLED", "DISABLED", "READY", "UNKNOWN", "PAUSED"];
-var statusStringMap = {
- "FAILED": "Failed",
- "SUCCEEDED": "Success",
- "FAILED_FINISHING": "Running w/Failure",
- "RUNNING": "Running",
- "WAITING": "Waiting",
- "KILLED": "Killed",
- "DISABLED": "Disabled",
- "READY": "Ready",
- "UNKNOWN": "Unknown",
- "PAUSED": "Paused"
-};
-
var handleJobMenuClick = function(action, el, pos) {
var jobid = el[0].jobid;
var requestURL = contextURL + "/manager?project=" + projectName + "&flow=" + flowName + "&job=" + jobid;
@@ -25,32 +11,6 @@ var handleJobMenuClick = function(action, el, pos) {
}
}
-function hasClass(el, name)
-{
- var classes = el.getAttribute("class");
- if (classes == null) {
- return false;
- }
- return new RegExp('(\\s|^)'+name+'(\\s|$)').test(classes);
-}
-
-function addClass(el, name)
-{
- if (!hasClass(el, name)) {
- var classes = el.getAttribute("class");
- classes += classes ? ' ' + name : '' +name;
- el.setAttribute("class", classes);
- }
-}
-
-function removeClass(el, name)
-{
- if (hasClass(el, name)) {
- var classes = el.getAttribute("class");
- el.setAttribute("class", classes.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, ''));
- }
-}
-
var statusView;
azkaban.StatusView= Backbone.View.extend({
initialize : function(settings) {
@@ -271,420 +231,7 @@ var showDialog = function(title, message) {
}
var jobListView;
-azkaban.JobListView = Backbone.View.extend({
- events: {
- "keyup input": "filterJobs",
- "click li": "handleJobClick",
- "click #resetPanZoomBtn" : "handleResetPanZoom"
- },
- initialize: function(settings) {
- this.model.bind('change:selected', this.handleSelectionChange, this);
- this.model.bind('change:graph', this.render, this);
- this.model.bind('change:update', this.handleStatusUpdate, this);
- },
- filterJobs: function(self) {
- var filter = $("#filter").val();
-
- if (filter && filter.trim() != "") {
- filter = filter.trim();
-
- if (filter == "") {
- if (this.filter) {
- $("#jobs").children().each(
- function(){
- var a = $(this).find("a");
- $(a).html(this.jobid);
- $(this).show();
- }
- );
- }
-
- this.filter = null;
- return;
- }
- }
- else {
- if (this.filter) {
- $("#jobs").children().each(
- function(){
- var a = $(this).find("a");
- $(a).html(this.jobid);
- $(this).show();
- }
- );
- }
-
- this.filter = null;
- return;
- }
-
- $("#jobs").children().each(
- function(){
- var jobid = this.jobid;
- var index = jobid.indexOf(filter);
- if (index != -1) {
- var a = $(this).find("a");
-
- var endIndex = index + filter.length;
- var newHTML = jobid.substring(0, index) + "<span>" + jobid.substring(index, endIndex) + "</span>" + jobid.substring(endIndex, jobid.length);
-
- $(a).html(newHTML);
- $(this).show();
- }
- else {
- $(this).hide();
- }
- });
-
- this.filter = filter;
- },
- render: function(self) {
- var data = this.model.get("data");
- var nodes = data.nodes;
- var edges = data.edges;
-
- this.listNodes = {};
- if (nodes.length == 0) {
- console.log("No results");
- return;
- };
-
- var nodeArray = nodes.slice(0);
- nodeArray.sort(function(a,b){
- var diff = a.y - b.y;
- if (diff == 0) {
- return a.x - b.x;
- }
- else {
- return diff;
- }
- });
-
- var ul = document.createElement("ul");
- $(ul).attr("id", "jobs");
- for (var i = 0; i < nodeArray.length; ++i) {
- var li = document.createElement("li");
-
- var iconDiv = document.createElement("div");
- $(iconDiv).addClass("icon");
- li.appendChild(iconDiv);
-
- var a = document.createElement("a");
- $(a).text(nodeArray[i].id);
- li.appendChild(a);
- ul.appendChild(li);
- li.jobid=nodeArray[i].id;
-
- $(li).contextMenu({
- menu: 'jobMenu'
- },
- handleJobMenuClick
- );
-
- this.listNodes[nodeArray[i].id] = li;
- }
-
- $("#list").append(ul);
- this.assignInitialStatus(self);
- },
- handleJobClick : function(evt) {
- var jobid = evt.currentTarget.jobid;
- if(!evt.currentTarget.jobid) {
- return;
- }
-
- if (this.model.has("selected")) {
- var selected = this.model.get("selected");
- if (selected == jobid) {
- this.model.unset("selected");
- }
- else {
- this.model.set({"selected": jobid});
- }
- }
- else {
- this.model.set({"selected": jobid});
- }
- },
- handleStatusUpdate: function(evt) {
- var updateData = this.model.get("update");
- for (var i = 0; i < updateData.nodes.length; ++i) {
- var updateNode = updateData.nodes[i];
- $(this.listNodes[updateNode.id]).addClass(updateNode.status);
- }
- },
- assignInitialStatus: function(evt) {
- var data = this.model.get("data");
- for (var i = 0; i < data.nodes.length; ++i) {
- var updateNode = data.nodes[i];
-
- $(this.listNodes[updateNode.id]).addClass(updateNode.status);
- }
- },
- handleSelectionChange: function(evt) {
- if (!this.model.hasChanged("selected")) {
- return;
- }
-
- var previous = this.model.previous("selected");
- var current = this.model.get("selected");
-
- if (previous) {
- $(this.listNodes[previous]).removeClass("selected");
- }
-
- if (current) {
- $(this.listNodes[current]).addClass("selected");
- }
- },
- handleResetPanZoom: function(evt) {
- this.model.trigger("resetPanZoom");
- }
-});
-
var svgGraphView;
-azkaban.SvgGraphView = Backbone.View.extend({
- events: {
- "click g" : "clickGraph"
- },
- initialize: function(settings) {
- this.model.bind('change:selected', this.changeSelected, this);
- this.model.bind('change:graph', this.render, this);
- this.model.bind('resetPanZoom', this.resetPanZoom, this);
- this.model.bind('change:update', this.handleStatusUpdate, this);
-
- this.svgns = "http://www.w3.org/2000/svg";
- this.xlinksn = "http://www.w3.org/1999/xlink";
-
- var graphDiv = this.el[0];
- var svg = $('#svgGraph')[0];
- this.svgGraph = svg;
-
- var gNode = document.createElementNS(this.svgns, 'g');
- gNode.setAttribute("id", "group");
- svg.appendChild(gNode);
- this.mainG = gNode;
-
- $(svg).svgNavigate();
- },
- initializeDefs: function(self) {
- var def = document.createElementNS(svgns, 'defs');
- def.setAttributeNS(null, "id", "buttonDefs");
-
- // ArrowHead
- var arrowHeadMarker = document.createElementNS(svgns, 'marker');
- arrowHeadMarker.setAttribute("id", "triangle");
- arrowHeadMarker.setAttribute("viewBox", "0 0 10 10");
- arrowHeadMarker.setAttribute("refX", "5");
- arrowHeadMarker.setAttribute("refY", "5");
- arrowHeadMarker.setAttribute("markerUnits", "strokeWidth");
- arrowHeadMarker.setAttribute("markerWidth", "4");
- arrowHeadMarker.setAttribute("markerHeight", "3");
- arrowHeadMarker.setAttribute("orient", "auto");
- var path = document.createElementNS(svgns, 'polyline');
- arrowHeadMarker.appendChild(path);
- path.setAttribute("points", "0,0 10,5 0,10 1,5");
-
- def.appendChild(arrowHeadMarker);
-
- this.svgGraph.appendChild(def);
- },
- render: function(self) {
- console.log("graph render");
-
- var data = this.model.get("data");
- var nodes = data.nodes;
- var edges = data.edges;
- if (nodes.length == 0) {
- console.log("No results");
- return;
- };
-
- // layout
- layoutGraph(nodes, edges);
-
- var bounds = {};
- this.nodes = {};
- for (var i = 0; i < nodes.length; ++i) {
- this.nodes[nodes[i].id] = nodes[i];
- }
-
- for (var i = 0; i < edges.length; ++i) {
- this.drawEdge(this, edges[i]);
- }
-
- for (var i = 0; i < nodes.length; ++i) {
- this.drawNode(this, nodes[i], bounds);
- }
-
- bounds.minX = bounds.minX ? bounds.minX - 200 : -200;
- bounds.minY = bounds.minY ? bounds.minY - 200 : -200;
- bounds.maxX = bounds.maxX ? bounds.maxX + 200 : 200;
- bounds.maxY = bounds.maxY ? bounds.maxY + 200 : 200;
-
- this.assignInitialStatus(self);
- this.graphBounds = bounds;
- this.resetPanZoom();
- },
- assignInitialStatus: function(evt) {
- var data = this.model.get("data");
- for (var i = 0; i < data.nodes.length; ++i) {
- var updateNode = data.nodes[i];
- var g = document.getElementById(updateNode.id);
- addClass(g, updateNode.status);
- }
- },
- changeSelected: function(self) {
- console.log("change selected");
- var selected = this.model.get("selected");
- var previous = this.model.previous("selected");
-
- if (previous) {
- // Unset previous
- var g = document.getElementById(previous);
- removeClass(g, "selected");
- }
-
- if (selected) {
- var g = document.getElementById(selected);
- var node = this.nodes[selected];
-
- addClass(g, "selected");
-
- var offset = 200;
- var widthHeight = offset*2;
- var x = node.x - offset;
- var y = node.y - offset;
-
- $("#svgGraph").svgNavigate("transformToBox", {x: x, y: y, width: widthHeight, height: widthHeight});
- }
- },
- handleStatusUpdate: function(evt) {
- var updateData = this.model.get("update");
- for (var i = 0; i < updateData.nodes.length; ++i) {
- var updateNode = updateData.nodes[i];
- var g = document.getElementById(updateNode.id);
-
- for (var j = 0; j < statusList.length; ++j) {
- var status = statusList[j];
- removeClass(g, status);
- }
-
- addClass(g, updateNode.status);
- }
- },
- clickGraph: function(self) {
- console.log("click");
- if (self.currentTarget.jobid) {
- this.model.set({"selected": self.currentTarget.jobid});
- }
- },
- drawEdge: function(self, edge) {
- var svg = self.svgGraph;
- var svgns = self.svgns;
-
- var startNode = this.nodes[edge.from];
- var endNode = this.nodes[edge.target];
-
- if (edge.guides) {
- var pointString = "" + startNode.x + "," + startNode.y + " ";
-
- for (var i = 0; i < edge.guides.length; ++i ) {
- edgeGuidePoint = edge.guides[i];
- pointString += edgeGuidePoint.x + "," + edgeGuidePoint.y + " ";
- }
-
- pointString += endNode.x + "," + endNode.y;
- var polyLine = document.createElementNS(svgns, "polyline");
- polyLine.setAttributeNS(null, "class", "edge");
- polyLine.setAttributeNS(null, "points", pointString);
- polyLine.setAttributeNS(null, "style", "fill:none;");
- self.mainG.appendChild(polyLine);
- }
- else {
- var line = document.createElementNS(svgns, 'line');
- line.setAttributeNS(null, "class", "edge");
- line.setAttributeNS(null, "x1", startNode.x);
- line.setAttributeNS(null, "y1", startNode.y);
- line.setAttributeNS(null, "x2", endNode.x);
- line.setAttributeNS(null, "y2", endNode.y);
-
- self.mainG.appendChild(line);
- }
- },
- drawNode: function(self, node, bounds) {
- var svg = self.svgGraph;
- var svgns = self.svgns;
-
- var xOffset = 10;
- var yOffset = 10;
-
- var nodeG = document.createElementNS(svgns, "g");
- nodeG.setAttributeNS(null, "class", "jobnode");
- nodeG.setAttributeNS(null, "id", node.id);
- nodeG.setAttributeNS(null, "font-family", "helvetica");
- nodeG.setAttributeNS(null, "transform", "translate(" + node.x + "," + node.y + ")");
-
- var innerG = document.createElementNS(svgns, "g");
- innerG.setAttributeNS(null, "transform", "translate(-10,-10)");
-
- var circle = document.createElementNS(svgns, 'circle');
- circle.setAttributeNS(null, "cy", 10);
- circle.setAttributeNS(null, "cx", 10);
- circle.setAttributeNS(null, "r", 12);
- circle.setAttributeNS(null, "style", "width:inherit;stroke-opacity:1");
-
-
- var text = document.createElementNS(svgns, 'text');
- var textLabel = document.createTextNode(node.label);
- text.appendChild(textLabel);
- text.setAttributeNS(null, "x", 4);
- text.setAttributeNS(null, "y", 15);
- text.setAttributeNS(null, "height", 10);
-
- this.addBounds(bounds, {minX:node.x - xOffset, minY: node.y - yOffset, maxX: node.x + xOffset, maxY: node.y + yOffset});
-
- var backRect = document.createElementNS(svgns, 'rect');
- backRect.setAttributeNS(null, "x", 0);
- backRect.setAttributeNS(null, "y", 2);
- backRect.setAttributeNS(null, "class", "backboard");
- backRect.setAttributeNS(null, "width", 10);
- backRect.setAttributeNS(null, "height", 15);
-
- innerG.appendChild(circle);
- innerG.appendChild(backRect);
- innerG.appendChild(text);
- innerG.jobid = node.id;
-
- nodeG.appendChild(innerG);
- self.mainG.appendChild(nodeG);
-
- // Need to get text width after attaching to SVG.
- var computeText = text.getComputedTextLength();
- var halfWidth = computeText/2;
- text.setAttributeNS(null, "x", -halfWidth + 10);
- backRect.setAttributeNS(null, "x", -halfWidth);
- backRect.setAttributeNS(null, "width", computeText + 20);
-
- nodeG.setAttributeNS(null, "class", "node");
- nodeG.jobid=node.id;
- $(nodeG).contextMenu({
- menu: 'jobMenu'
- },
- handleJobMenuClick
- );
- },
- addBounds: function(toBounds, addBounds) {
- toBounds.minX = toBounds.minX ? Math.min(toBounds.minX, addBounds.minX) : addBounds.minX;
- toBounds.minY = toBounds.minY ? Math.min(toBounds.minY, addBounds.minY) : addBounds.minY;
- toBounds.maxX = toBounds.maxX ? Math.max(toBounds.maxX, addBounds.maxX) : addBounds.maxX;
- toBounds.maxY = toBounds.maxY ? Math.max(toBounds.maxY, addBounds.maxY) : addBounds.maxY;
- },
- resetPanZoom : function(self) {
- var bounds = this.graphBounds;
- $("#svgGraph").svgNavigate("transformToBox", {x: bounds.minX, y: bounds.minY, width: (bounds.maxX - bounds.minX), height: (bounds.maxY - bounds.minY) });
- }
-});
var executionListView;
azkaban.ExecutionListView = Backbone.View.extend({
src/web/js/azkaban.flow.graph.view.js 266(+266 -0)
diff --git a/src/web/js/azkaban.flow.graph.view.js b/src/web/js/azkaban.flow.graph.view.js
new file mode 100644
index 0000000..75b3096
--- /dev/null
+++ b/src/web/js/azkaban.flow.graph.view.js
@@ -0,0 +1,266 @@
+var svgGraphView;
+azkaban.SvgGraphView = Backbone.View.extend({
+ events: {
+ "click g" : "clickGraph"
+ },
+ initialize: function(settings) {
+ this.model.bind('change:selected', this.changeSelected, this);
+ this.model.bind('change:graph', this.render, this);
+ this.model.bind('resetPanZoom', this.resetPanZoom, this);
+ this.model.bind('change:update', this.handleStatusUpdate, this);
+ this.model.bind('change:disabled', this.handleDisabledChange, this);
+
+ this.svgns = "http://www.w3.org/2000/svg";
+ this.xlinksn = "http://www.w3.org/1999/xlink";
+
+ var graphDiv = this.el[0];
+ var svg = $(this.el).find('svg')[0];
+ this.svgGraph = svg;
+
+ var gNode = document.createElementNS(this.svgns, 'g');
+ svg.appendChild(gNode);
+ this.mainG = gNode;
+
+ $(svg).svgNavigate();
+ },
+ initializeDefs: function(self) {
+ var def = document.createElementNS(svgns, 'defs');
+ def.setAttributeNS(null, "id", "buttonDefs");
+
+ // ArrowHead
+ var arrowHeadMarker = document.createElementNS(svgns, 'marker');
+ arrowHeadMarker.setAttribute("id", "triangle");
+ arrowHeadMarker.setAttribute("viewBox", "0 0 10 10");
+ arrowHeadMarker.setAttribute("refX", "5");
+ arrowHeadMarker.setAttribute("refY", "5");
+ arrowHeadMarker.setAttribute("markerUnits", "strokeWidth");
+ arrowHeadMarker.setAttribute("markerWidth", "4");
+ arrowHeadMarker.setAttribute("markerHeight", "3");
+ arrowHeadMarker.setAttribute("orient", "auto");
+ var path = document.createElementNS(svgns, 'polyline');
+ arrowHeadMarker.appendChild(path);
+ path.setAttribute("points", "0,0 10,5 0,10 1,5");
+
+ def.appendChild(arrowHeadMarker);
+
+ this.svgGraph.appendChild(def);
+ },
+ render: function(self) {
+ console.log("graph render");
+
+ var data = this.model.get("data");
+ var nodes = data.nodes;
+ var edges = data.edges;
+ if (nodes.length == 0) {
+ console.log("No results");
+ return;
+ };
+
+ // layout
+ layoutGraph(nodes, edges);
+
+ var bounds = {};
+ this.nodes = {};
+ for (var i = 0; i < nodes.length; ++i) {
+ this.nodes[nodes[i].id] = nodes[i];
+ }
+
+ for (var i = 0; i < edges.length; ++i) {
+ this.drawEdge(this, edges[i]);
+ }
+
+ this.gNodes = {};
+ for (var i = 0; i < nodes.length; ++i) {
+ this.drawNode(this, nodes[i], bounds);
+ }
+
+ bounds.minX = bounds.minX ? bounds.minX - 200 : -200;
+ bounds.minY = bounds.minY ? bounds.minY - 200 : -200;
+ bounds.maxX = bounds.maxX ? bounds.maxX + 200 : 200;
+ bounds.maxY = bounds.maxY ? bounds.maxY + 200 : 200;
+
+ this.assignInitialStatus(self);
+ this.graphBounds = bounds;
+ this.resetPanZoom(0);
+ },
+ handleDisabledChange: function(evt) {
+ var disabledMap = this.model.get("disabled");
+ for(var id in disabledMap) {
+ if(disabledMap.hasOwnProperty(id)) {
+ var disabled = disabledMap[id];
+ this.nodes[id].disabled = disabled;
+ var g = this.gNodes[id];
+
+ if (disabled) {
+ this.nodes[id].disabled = disabled;
+ addClass(g, "disabled");
+ }
+ else {
+ removeClass(g, "disabled");
+ }
+ }
+ }
+ },
+ assignInitialStatus: function(evt) {
+ var data = this.model.get("data");
+ for (var i = 0; i < data.nodes.length; ++i) {
+ var updateNode = data.nodes[i];
+ var g = this.gNodes[updateNode.id];
+ addClass(g, updateNode.status);
+ }
+ },
+ changeSelected: function(self) {
+ console.log("change selected");
+ var selected = this.model.get("selected");
+ var previous = this.model.previous("selected");
+
+ if (previous) {
+ // Unset previous
+ var g = this.gNodes[previous];
+ removeClass(g, "selected");
+ }
+
+ if (selected) {
+ var g = this.gNodes[selected];
+ var node = this.nodes[selected];
+
+ addClass(g, "selected");
+
+ var offset = 200;
+ var widthHeight = offset*2;
+ var x = node.x - offset;
+ var y = node.y - offset;
+
+ $(this.svgGraph).svgNavigate("transformToBox", {x: x, y: y, width: widthHeight, height: widthHeight});
+ }
+ },
+ handleStatusUpdate: function(evt) {
+ var updateData = this.model.get("update");
+ for (var i = 0; i < updateData.nodes.length; ++i) {
+ var updateNode = updateData.nodes[i];
+
+ var g = this.gNodes[updateNode.id];
+
+ for (var j = 0; j < statusList.length; ++j) {
+ var status = statusList[j];
+ removeClass(g, status);
+ }
+
+ addClass(g, updateNode.status);
+ }
+ },
+ clickGraph: function(self) {
+ console.log("click");
+ if (self.currentTarget.jobid) {
+ this.model.set({"selected": self.currentTarget.jobid});
+ }
+ },
+ drawEdge: function(self, edge) {
+ var svg = self.svgGraph;
+ var svgns = self.svgns;
+
+ var startNode = this.nodes[edge.from];
+ var endNode = this.nodes[edge.target];
+
+ if (edge.guides) {
+ var pointString = "" + startNode.x + "," + startNode.y + " ";
+
+ for (var i = 0; i < edge.guides.length; ++i ) {
+ edgeGuidePoint = edge.guides[i];
+ pointString += edgeGuidePoint.x + "," + edgeGuidePoint.y + " ";
+ }
+
+ pointString += endNode.x + "," + endNode.y;
+ var polyLine = document.createElementNS(svgns, "polyline");
+ polyLine.setAttributeNS(null, "class", "edge");
+ polyLine.setAttributeNS(null, "points", pointString);
+ polyLine.setAttributeNS(null, "style", "fill:none;");
+ self.mainG.appendChild(polyLine);
+ }
+ else {
+ var line = document.createElementNS(svgns, 'line');
+ line.setAttributeNS(null, "class", "edge");
+ line.setAttributeNS(null, "x1", startNode.x);
+ line.setAttributeNS(null, "y1", startNode.y);
+ line.setAttributeNS(null, "x2", endNode.x);
+ line.setAttributeNS(null, "y2", endNode.y);
+
+ self.mainG.appendChild(line);
+ }
+ },
+ drawNode: function(self, node, bounds) {
+ var svg = self.svgGraph;
+ var svgns = self.svgns;
+
+ var xOffset = 10;
+ var yOffset = 10;
+
+
+ var nodeG = document.createElementNS(svgns, "g");
+ nodeG.setAttributeNS(null, "class", "jobnode");
+ nodeG.setAttributeNS(null, "font-family", "helvetica");
+ nodeG.setAttributeNS(null, "transform", "translate(" + node.x + "," + node.y + ")");
+ this.gNodes[node.id] = nodeG;
+
+ var innerG = document.createElementNS(svgns, "g");
+ innerG.setAttributeNS(null, "transform", "translate(-10,-10)");
+
+ var circle = document.createElementNS(svgns, 'circle');
+ circle.setAttributeNS(null, "cy", 10);
+ circle.setAttributeNS(null, "cx", 10);
+ circle.setAttributeNS(null, "r", 12);
+ circle.setAttributeNS(null, "style", "width:inherit;stroke-opacity:1");
+
+
+ var text = document.createElementNS(svgns, 'text');
+ var textLabel = document.createTextNode(node.label);
+ text.appendChild(textLabel);
+ text.setAttributeNS(null, "x", 4);
+ text.setAttributeNS(null, "y", 15);
+ text.setAttributeNS(null, "height", 10);
+
+ this.addBounds(bounds, {minX:node.x - xOffset, minY: node.y - yOffset, maxX: node.x + xOffset, maxY: node.y + yOffset});
+
+ var backRect = document.createElementNS(svgns, 'rect');
+ backRect.setAttributeNS(null, "x", 0);
+ backRect.setAttributeNS(null, "y", 2);
+ backRect.setAttributeNS(null, "class", "backboard");
+ backRect.setAttributeNS(null, "width", 10);
+ backRect.setAttributeNS(null, "height", 15);
+
+ innerG.appendChild(circle);
+ innerG.appendChild(backRect);
+ innerG.appendChild(text);
+ innerG.jobid = node.id;
+
+ nodeG.appendChild(innerG);
+ self.mainG.appendChild(nodeG);
+
+ // Need to get text width after attaching to SVG.
+ var computeText = text.getComputedTextLength();
+ var halfWidth = computeText/2;
+ text.setAttributeNS(null, "x", -halfWidth + 10);
+ backRect.setAttributeNS(null, "x", -halfWidth);
+ backRect.setAttributeNS(null, "width", computeText + 20);
+
+ nodeG.setAttributeNS(null, "class", "node");
+ nodeG.jobid=node.id;
+ $(nodeG).contextMenu({
+ menu: 'jobMenu'
+ },
+ handleJobMenuClick
+ );
+ },
+ addBounds: function(toBounds, addBounds) {
+ toBounds.minX = toBounds.minX ? Math.min(toBounds.minX, addBounds.minX) : addBounds.minX;
+ toBounds.minY = toBounds.minY ? Math.min(toBounds.minY, addBounds.minY) : addBounds.minY;
+ toBounds.maxX = toBounds.maxX ? Math.max(toBounds.maxX, addBounds.maxX) : addBounds.maxX;
+ toBounds.maxY = toBounds.maxY ? Math.max(toBounds.maxY, addBounds.maxY) : addBounds.maxY;
+ },
+ 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 };
+
+ $(this.svgGraph).svgNavigate("transformToBox", param);
+ }
+});
\ No newline at end of file
src/web/js/azkaban.flow.job.view.js 189(+189 -0)
diff --git a/src/web/js/azkaban.flow.job.view.js b/src/web/js/azkaban.flow.job.view.js
new file mode 100644
index 0000000..210b404
--- /dev/null
+++ b/src/web/js/azkaban.flow.job.view.js
@@ -0,0 +1,189 @@
+azkaban.JobListView = Backbone.View.extend({
+ events: {
+ "keyup input": "filterJobs",
+ "click li": "handleJobClick",
+ "click .resetPanZoomBtn" : "handleResetPanZoom"
+ },
+ initialize: function(settings) {
+ this.model.bind('change:selected', this.handleSelectionChange, this);
+ this.model.bind('change:disabled', this.handleDisabledChange, this);
+ this.model.bind('change:graph', this.render, this);
+ this.model.bind('change:update', this.handleStatusUpdate, this);
+
+ this.filterInput = $(this.el).find(".filter");
+ this.list = $(this.el).find(".list");
+ },
+ filterJobs: function(self) {
+ var filter = this.filterInput.val();
+
+ if (filter && filter.trim() != "") {
+ filter = filter.trim();
+
+ if (filter == "") {
+ if (this.filter) {
+ this.jobs.children().each(
+ function(){
+ var a = $(this).find("a");
+ $(a).html(this.jobid);
+ $(this).show();
+ }
+ );
+ }
+
+ this.filter = null;
+ return;
+ }
+ }
+ else {
+ if (this.filter) {
+ this.jobs.children().each(
+ function(){
+ var a = $(this).find("a");
+ $(a).html(this.jobid);
+ $(this).show();
+ }
+ );
+ }
+
+ this.filter = null;
+ return;
+ }
+
+ this.jobs.children().each(
+ function(){
+ var jobid = this.jobid;
+ var index = jobid.indexOf(filter);
+ if (index != -1) {
+ var a = $(this).find("a");
+
+ var endIndex = index + filter.length;
+ var newHTML = jobid.substring(0, index) + "<span>" + jobid.substring(index, endIndex) + "</span>" + jobid.substring(endIndex, jobid.length);
+
+ $(a).html(newHTML);
+ $(this).show();
+ }
+ else {
+ $(this).hide();
+ }
+ });
+
+ this.filter = filter;
+ },
+ handleStatusUpdate: function(evt) {
+ var updateData = this.model.get("update");
+ for (var i = 0; i < updateData.nodes.length; ++i) {
+ var updateNode = updateData.nodes[i];
+ $(this.listNodes[updateNode.id]).addClass(updateNode.status);
+ }
+ },
+ assignInitialStatus: function(evt) {
+ var data = this.model.get("data");
+ for (var i = 0; i < data.nodes.length; ++i) {
+ var updateNode = data.nodes[i];
+
+ $(this.listNodes[updateNode.id]).addClass(updateNode.status);
+ }
+ },
+ render: function(self) {
+ var data = this.model.get("data");
+ var nodes = data.nodes;
+ var edges = data.edges;
+
+ this.listNodes = {};
+ if (nodes.length == 0) {
+ console.log("No results");
+ return;
+ };
+
+ var nodeArray = nodes.slice(0);
+ nodeArray.sort(function(a,b){
+ var diff = a.y - b.y;
+ if (diff == 0) {
+ return a.x - b.x;
+ }
+ else {
+ return diff;
+ }
+ });
+
+ var ul = document.createElement("ul");
+ $(ul).attr("class", "jobs");
+ this.jobs = $(ul);
+
+ for (var i = 0; i < nodeArray.length; ++i) {
+ var li = document.createElement("li");
+ var iconDiv = document.createElement("div");
+ $(iconDiv).addClass("icon");
+ li.appendChild(iconDiv);
+
+ var a = document.createElement("a");
+ $(a).text(nodeArray[i].id);
+ li.appendChild(a);
+ ul.appendChild(li);
+ li.jobid=nodeArray[i].id;
+
+ $(li).contextMenu({
+ menu: 'jobMenu'
+ },
+ handleJobMenuClick
+ );
+
+ this.listNodes[nodeArray[i].id] = li;
+ }
+
+ this.list.append(ul);
+ this.assignInitialStatus(self);
+ },
+ handleJobClick : function(evt) {
+ var jobid = evt.currentTarget.jobid;
+ if(!evt.currentTarget.jobid) {
+ return;
+ }
+
+ if (this.model.has("selected")) {
+ var selected = this.model.get("selected");
+ if (selected == jobid) {
+ this.model.unset("selected");
+ }
+ else {
+ this.model.set({"selected": jobid});
+ }
+ }
+ else {
+ this.model.set({"selected": jobid});
+ }
+ },
+ handleDisabledChange: function(evt) {
+ var disabledMap = this.model.get("disabled");
+ for(var id in disabledMap) {
+ if(disabledMap.hasOwnProperty(id)) {
+ var disabled = (disabledMap[id]);
+ if (disabled) {
+ $(this.listNodes[id]).addClass("nodedisabled");
+ }
+ else {
+ $(this.listNodes[id]).removeClass("nodedisabled");
+ }
+ }
+ }
+ },
+ handleSelectionChange: function(evt) {
+ if (!this.model.hasChanged("selected")) {
+ return;
+ }
+
+ var previous = this.model.previous("selected");
+ var current = this.model.get("selected");
+
+ if (previous) {
+ $(this.listNodes[previous]).removeClass("selected");
+ }
+
+ if (current) {
+ $(this.listNodes[current]).addClass("selected");
+ }
+ },
+ handleResetPanZoom: function(evt) {
+ this.model.trigger("resetPanZoom");
+ }
+});
src/web/js/azkaban.flow.view.js 228(+3 -225)
diff --git a/src/web/js/azkaban.flow.view.js b/src/web/js/azkaban.flow.view.js
index c8aef95..d65dc9d 100644
--- a/src/web/js/azkaban.flow.view.js
+++ b/src/web/js/azkaban.flow.view.js
@@ -214,171 +214,9 @@ azkaban.FlowTabView= Backbone.View.extend({
});
var jobListView;
-azkaban.JobListView = Backbone.View.extend({
- events: {
- "keyup input": "filterJobs",
- "click li": "handleJobClick",
- "click #resetPanZoomBtn" : "handleResetPanZoom"
- },
- initialize: function(settings) {
- this.model.bind('change:selected', this.handleSelectionChange, this);
- this.model.bind('change:disabled', this.handleDisabledChange, this);
- this.model.bind('change:graph', this.render, this);
- },
- filterJobs: function(self) {
- var filter = $("#filter").val();
-
- if (filter && filter.trim() != "") {
- filter = filter.trim();
-
- if (filter == "") {
- if (this.filter) {
- $("#jobs").children().each(
- function(){
- var a = $(this).find("a");
- $(a).html(this.jobid);
- $(this).show();
- }
- );
- }
-
- this.filter = null;
- return;
- }
- }
- else {
- if (this.filter) {
- $("#jobs").children().each(
- function(){
- var a = $(this).find("a");
- $(a).html(this.jobid);
- $(this).show();
- }
- );
- }
-
- this.filter = null;
- return;
- }
-
- $("#jobs").children().each(
- function(){
- var jobid = this.jobid;
- var index = jobid.indexOf(filter);
- if (index != -1) {
- var a = $(this).find("a");
-
- var endIndex = index + filter.length;
- var newHTML = jobid.substring(0, index) + "<span>" + jobid.substring(index, endIndex) + "</span>" + jobid.substring(endIndex, jobid.length);
-
- $(a).html(newHTML);
- $(this).show();
- }
- else {
- $(this).hide();
- }
- });
-
- this.filter = filter;
- },
- render: function(self) {
- var data = this.model.get("data");
- var nodes = data.nodes;
- var edges = data.edges;
-
- this.listNodes = {};
- if (nodes.length == 0) {
- console.log("No results");
- return;
- };
-
- var nodeArray = nodes.slice(0);
- nodeArray.sort(function(a,b){
- var diff = a.y - b.y;
- if (diff == 0) {
- return a.x - b.x;
- }
- else {
- return diff;
- }
- });
-
- var ul = document.createElement("ul");
- $(ul).attr("id", "jobs");
- for (var i = 0; i < nodeArray.length; ++i) {
- var li = document.createElement("li");
- var a = document.createElement("a");
- $(a).text(nodeArray[i].id);
- li.appendChild(a);
- ul.appendChild(li);
- li.jobid=nodeArray[i].id;
-
- $(li).contextMenu({
- menu: 'jobMenu'
- },
- handleJobMenuClick
- );
-
- this.listNodes[nodeArray[i].id] = li;
- }
-
- $("#list").append(ul);
- },
- handleJobClick : function(evt) {
- var jobid = evt.currentTarget.jobid;
- if(!evt.currentTarget.jobid) {
- return;
- }
-
- if (this.model.has("selected")) {
- var selected = this.model.get("selected");
- if (selected == jobid) {
- this.model.unset("selected");
- }
- else {
- this.model.set({"selected": jobid});
- }
- }
- else {
- this.model.set({"selected": jobid});
- }
- },
- handleDisabledChange: function(evt) {
- var disabledMap = this.model.get("disabled");
- for(var id in disabledMap) {
- if(disabledMap.hasOwnProperty(id)) {
- var disabled = (disabledMap[id]);
- if (disabled) {
- $(this.listNodes[id]).addClass("nodedisabled");
- }
- else {
- $(this.listNodes[id]).removeClass("nodedisabled");
- }
- }
- }
- },
- handleSelectionChange: function(evt) {
- if (!this.model.hasChanged("selected")) {
- return;
- }
-
- var previous = this.model.previous("selected");
- var current = this.model.get("selected");
-
- if (previous) {
- $(this.listNodes[previous]).removeClass("selected");
- }
-
- if (current) {
- $(this.listNodes[current]).addClass("selected");
- }
- },
- handleResetPanZoom: function(evt) {
- this.model.trigger("resetPanZoom");
- }
-});
var svgGraphView;
+/*
azkaban.SvgGraphView = Backbone.View.extend({
events: {
"click g" : "clickGraph"
@@ -617,7 +455,7 @@ azkaban.SvgGraphView = Backbone.View.extend({
$("#svgGraph").svgNavigate("transformToBox", {x: bounds.minX, y: bounds.minY, width: (bounds.maxX - bounds.minX), height: (bounds.maxY - bounds.minY) });
}
});
-
+*/
var executionsView;
azkaban.ExecutionsView = Backbone.View.extend({
events: {
@@ -927,72 +765,12 @@ azkaban.ScheduleFlowView = Backbone.View.extend({
}
});
-var executeFlowView;
-azkaban.ExecuteFlowView = Backbone.View.extend({
- events : {
- "click #execute-btn": "handleExecuteFlow",
- "click #execute-custom-btn": "handleCustomFlow",
- "click #cancel-btn": "handleCancelExecution",
- "click .modal-close": "handleCancelExecution"
- },
- initialize: function(evt) {
- $('#executebtn').click( function() {
- $('#modalBackground').show();
- $('#executing-options').show();
- });
-
- /*
- $('#executebtn').click( function() {
- console.log("Executing button clicked");
- $('#executing-options').modal({
- closeHTML: "<a href='#' title='Close' class='modal-close'>x</a>",
- position: ["10%",],
- containerId: 'confirm-container',
- containerCss: {
-
- },
- opacity:40,
- overlayCss: {backgroundColor:"#000", width: '100%'},
- onShow: function (dialog) {
- var modal = this;
- $("#errorMsg").hide();
- }
- });
- });*/
- },
- handleCancelExecution: function(evt) {
- var executeURL = contextURL + "/executor";
- $('#modalBackground').hide();
- $('#executing-options').hide();
- },
- handleExecuteFlow: function(evt) {
- var executeURL = contextURL + "/executor";
- $.get(
- executeURL,
- {"project": projectName, "ajax":"executeFlow", "flow":flowName, "disabled":graphModel.get("disabled")},
- function(data) {
- if (data.error) {
- alert(data.error);
- }
- else {
- var redirectURL = contextURL + "/executor?execid=" + data.execid;
- window.location.href = redirectURL;
- }
- },
- "json"
- );
- },
- handleCustomFlow: function(evt) {
-
- }
-});
$(function() {
var selected;
// Execution model has to be created before the window switches the tabs.
executionModel = new azkaban.ExecutionModel();
- executionsView = new azkaban.ExecutionsView({el: $('#executionsView'), model: executionModel});
-
+
flowTabView = new azkaban.FlowTabView({el:$( '#headertabs'), selectedView: selected });
graphModel = new azkaban.GraphModel();
src/web/js/azkaban.job.status.utils.js 39(+39 -0)
diff --git a/src/web/js/azkaban.job.status.utils.js b/src/web/js/azkaban.job.status.utils.js
new file mode 100644
index 0000000..271af58
--- /dev/null
+++ b/src/web/js/azkaban.job.status.utils.js
@@ -0,0 +1,39 @@
+var statusList = ["FAILED", "FAILED_FINISHING", "SUCCEEDED", "RUNNING", "WAITING", "KILLED", "DISABLED", "READY", "UNKNOWN", "PAUSED"];
+var statusStringMap = {
+ "FAILED": "Failed",
+ "SUCCEEDED": "Success",
+ "FAILED_FINISHING": "Running w/Failure",
+ "RUNNING": "Running",
+ "WAITING": "Waiting",
+ "KILLED": "Killed",
+ "DISABLED": "Disabled",
+ "READY": "Ready",
+ "UNKNOWN": "Unknown",
+ "PAUSED": "Paused"
+};
+
+function hasClass(el, name)
+{
+ var classes = el.getAttribute("class");
+ if (classes == null) {
+ return false;
+ }
+ return new RegExp('(\\s|^)'+name+'(\\s|$)').test(classes);
+}
+
+function addClass(el, name)
+{
+ if (!hasClass(el, name)) {
+ var classes = el.getAttribute("class");
+ classes += classes ? ' ' + name : '' +name;
+ el.setAttribute("class", classes);
+ }
+}
+
+function removeClass(el, name)
+{
+ if (hasClass(el, name)) {
+ var classes = el.getAttribute("class");
+ el.setAttribute("class", classes.replace(new RegExp('(\\s|^)'+name+'(\\s|$)'),' ').replace(/^\s+|\s+$/g, ''));
+ }
+}
\ No newline at end of file
src/web/js/svgNavigate.js 8(+7 -1)
diff --git a/src/web/js/svgNavigate.js b/src/web/js/svgNavigate.js
index 0e547a1..076f700 100644
--- a/src/web/js/svgNavigate.js
+++ b/src/web/js/svgNavigate.js
@@ -298,6 +298,7 @@
var x = arguments.x;
var y = arguments.y;
var factor = 0.9;
+ var duration = arguments.duration;
var width = arguments.width ? arguments.width : 1;
var height = arguments.height ? arguments.height : 1;
@@ -319,7 +320,12 @@
var sx = (divWidth - scaledWidth)/2 -scale*x;
var sy = (divHeight - scaledHeight)/2 -scale*y;
console.log("sx,sy:" + sx + "," + sy);
- animateTransform(target, scale, sx, sy, 500);
+
+ if (duration != 0 && !duration) {
+ duration = 500;
+ }
+
+ animateTransform(target, scale, sx, sy, duration);
},
attachNavigateModel : function(arguments) {
var $this = $(this);