azkaban-developers
Details
diff --git a/src/java/azkaban/webapp/servlet/velocity/flowgraphview.vm b/src/java/azkaban/webapp/servlet/velocity/flowgraphview.vm
index 44d6654..ac2d107 100644
--- a/src/java/azkaban/webapp/servlet/velocity/flowgraphview.vm
+++ b/src/java/azkaban/webapp/servlet/velocity/flowgraphview.vm
@@ -24,12 +24,12 @@
<div class="panel-heading">
<input id="filter" type="text" placeholder="Job Filter" class="form-control">
</div>
- <div id="joblist" class="list-group"></div>
+ <div id="joblist"></div>
<div class="panel-footer">
<div id="autoPanZoom" class="checkbox">
<label>
- <input type="checkbox" id="autoPanZoomCheckbox" class="autoPanZoom" value="autoPanZoom" />Auto Pan Zoom
- </label>
+ <input type="checkbox" id="autoPanZoomCheckbox" class="autoPanZoom" value="autoPanZoom" />Auto Pan Zoom
+ </label>
</div>
<button type="button" class="btn btn-sm btn-default" id="resetPanZoomBtn">Reset Pan Zoom</button>
</div>
src/less/flow.less 171(+91 -80)
diff --git a/src/less/flow.less b/src/less/flow.less
index e08f0af..5b1a957 100644
--- a/src/less/flow.less
+++ b/src/less/flow.less
@@ -148,85 +148,96 @@ td {
// TODO: Rename this as #job-list
#joblist {
height: 100%;
- ul {
- list-style-type: none;
- padding-left: 0px;
-
- li {
- &.active > a {
- background-color: #D9EDFF;
- }
-
- ul {
- padding-left: 20px;
- }
-
- &.subFilter > a > .expandarrow {
- color : #3398cc;
- }
-
- > a {
- clear:both;
- border-bottom-width: 0;
-
- &.nodedisabled,
- &.DISABLED {
- opacity: 0.3;
- }
-
- &.DISABLED .icon {
- background-position: 16px 0px;
- }
-
- &.READY .icon {
- background-position: 16px 0px;
- }
-
- &.QUEUED .icon {
- opacity: 0.5;
- background-position: 32px 0px;
- }
-
- &.RUNNING .icon {
- background-position: 32px 0px;
- }
-
- &.SUCCEEDED .icon {
- background-position: 48px 0px;
- }
-
- &.FAILED .icon {
- background-position: 0px 0px;
- }
-
- &.KILLED .icon {
- background-position: 0px 0px;
- }
-
- &.FAILED_FINISHING .icon {
- background-position: 0px 0px;
- }
-
- .icon {
- float: left;
- width: 16px;
- height: 16px;
- margin: 2px 4px 0px -5px;
- background-image: url("./images/dot-icon.png");
- background-position: 16px 0px;
- }
-
- .expandarrow {
- float: right;
- width: 16px;
- height: 16px;
- font-size: 8pt;
- }
-
- .filterHighlight {
- background-color: #FFFF00;
- }
- }
- }
+}
+ul.tree-list {
+ list-style-type: none;
+ padding-left: 0px;
+ margin: 0;
+}
+
+li.tree-list-item {
+ &.active > a {
+ background-color: #D9EDFF;
+ }
+
+ ul.tree-list {
+ padding-left: 20px;
+ }
+
+ &.subFilter > a > .expandarrow {
+ color : #3398cc;
+ }
+
+ > a {
+ clear: both;
+ position: relative;
+ display: block;
+ border-bottom-width: 0;
+ padding: 10px 15px;
+
+ &:hover,
+ &:focus {
+ text-decoration: none;
+ background-color: #f5f5f5;
+ cursor: pointer;
+ }
+
+ &.nodedisabled,
+ &.DISABLED {
+ opacity: 0.3;
+ }
+
+ &.DISABLED .icon {
+ background-position: 16px 0px;
+ }
+
+ &.READY .icon {
+ background-position: 16px 0px;
+ }
+
+ &.QUEUED .icon {
+ opacity: 0.5;
+ background-position: 32px 0px;
+ }
+
+ &.RUNNING .icon {
+ background-position: 32px 0px;
+ }
+
+ &.SUCCEEDED .icon {
+ background-position: 48px 0px;
+ }
+
+ &.FAILED .icon {
+ background-position: 0px 0px;
+ }
+
+ &.KILLED .icon {
+ background-position: 0px 0px;
+ }
+
+ &.FAILED_FINISHING .icon {
+ background-position: 0px 0px;
+ }
+
+ .icon {
+ float: left;
+ width: 16px;
+ height: 16px;
+ margin: 2px 4px 0px -5px;
+ background-image: url("./images/dot-icon.png");
+ background-position: 16px 0px;
+ }
+
+ .expandarrow {
+ float: right;
+ width: 16px;
+ height: 16px;
+ font-size: 8pt;
+ }
+
+ .filterHighlight {
+ background-color: #FFFF00;
+ }
}
}
src/web/js/azkaban/view/flow-job.js 73(+47 -26)
diff --git a/src/web/js/azkaban/view/flow-job.js b/src/web/js/azkaban/view/flow-job.js
index c68e279..32bba07 100644
--- a/src/web/js/azkaban/view/flow-job.js
+++ b/src/web/js/azkaban/view/flow-job.js
@@ -20,10 +20,11 @@ azkaban.JobListView = Backbone.View.extend({
"click .job": "handleJobClick",
"click #resetPanZoomBtn": "handleResetPanZoom",
"contextmenu li.listElement": "handleContextMenuClick",
- "change .autoPanZoom" : "handleAutoPanZoom",
- "click .expandarrow" : "handleToggleMenuExpand"
+ "change .autoPanZoom": "handleAutoPanZoom",
+ "click .expandarrow": "handleToggleMenuExpand"
},
- initialize: function(settings) {
+
+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);
@@ -33,8 +34,8 @@ azkaban.JobListView = Backbone.View.extend({
this.list = $(this.el).find("#joblist");
this.contextMenu = settings.contextMenuCallback;
this.listNodes = {};
-
},
+
filterJobs: function(self) {
var filter = this.filterInput.val();
// Clear all filters first
@@ -54,28 +55,31 @@ azkaban.JobListView = Backbone.View.extend({
node.listElement = li;
var index = nodeName.indexOf(filter);
- if (index != -1) {
- var spanlabel = $(li).find("> a > span");
-
- var endIndex = index + filter.length;
- var newHTML = nodeName.substring(0, index) + "<span class=\"filterHighlight\">" +
+ if (index == -1) {
+ continue;
+ }
+
+ var spanlabel = $(li).find("> a > span");
+
+ var endIndex = index + filter.length;
+ var newHTML = nodeName.substring(0, index) + "<span class=\"filterHighlight\">" +
nodeName.substring(index, endIndex) + "</span>" +
nodeName.substring(endIndex, nodeName.length);
- $(spanlabel).html(newHTML);
-
- // Apply classes to all the included embedded flows.
- var pIndex = key.length;
- while((pIndex = key.lastIndexOf(":", pIndex - 1)) > 0) {
- var parentId = key.substr(0, pIndex);
- var parentLi = this.listNodes[parentId];
- $(parentLi).show();
- $(parentLi).addClass("subFilter");
- }
-
- $(li).show();
+ $(spanlabel).html(newHTML);
+
+ // Apply classes to all the included embedded flows.
+ var pIndex = key.length;
+ while ((pIndex = key.lastIndexOf(":", pIndex - 1)) > 0) {
+ var parentId = key.substr(0, pIndex);
+ var parentLi = this.listNodes[parentId];
+ $(parentLi).show();
+ $(parentLi).addClass("subFilter");
}
+
+ $(li).show();
}
},
+
hideAll: function(self) {
for (var key in this.listNodes) {
var li = this.listNodes[key];
@@ -85,6 +89,7 @@ azkaban.JobListView = Backbone.View.extend({
$(li).hide();
}
},
+
unfilterAll: function(self) {
for (var key in this.listNodes) {
var li = this.listNodes[key];
@@ -94,6 +99,7 @@ azkaban.JobListView = Backbone.View.extend({
$(li).show();
}
},
+
handleStatusUpdate: function(evt) {
var data = this.model.get("data");
var lastUpdateTime = this.model.get("lastUpdateTime");
@@ -101,6 +107,7 @@ azkaban.JobListView = Backbone.View.extend({
this.changeStatuses(data, lastUpdateTime);
}
},
+
changeStatuses: function(data, lastUpdateTime) {
for (var i = 0; i < data.nodes.length; ++i) {
var node = data.nodes[i];
@@ -117,17 +124,19 @@ azkaban.JobListView = Backbone.View.extend({
}
}
},
+
render: function(self) {
var data = this.model.get("data");
var nodes = data.nodes;
this.renderTree(this.list, data);
-//
-// this.assignInitialStatus(self);
+
+ //this.assignInitialStatus(self);
this.handleDisabledChange(self);
this.changeStatuses(data, 0);
},
- renderTree : function(el, data, prefix) {
+
+ renderTree: function(el, data, prefix) {
var nodes = data.nodes;
if (nodes.length == 0) {
console.log("No results");
@@ -149,9 +158,11 @@ azkaban.JobListView = Backbone.View.extend({
});
var ul = document.createElement('ul');
- for(var i=0; i < nodeArray.length; ++i) {
+ $(ul).addClass("tree-list");
+ for (var i = 0; i < nodeArray.length; ++i) {
var li = document.createElement("li");
$(li).addClass("listElement");
+ $(li).addClass("tree-list-item");
// This is used for the filter step.
var listNodeName = prefix + nodeArray[i].id;
@@ -164,7 +175,6 @@ azkaban.JobListView = Backbone.View.extend({
$(iconDiv).addClass('icon');
$(a).append(iconDiv);
- $(a).addClass('list-group-item').addClass('job');
var span = document.createElement("span");
$(span).text(nodeArray[i].id);
@@ -188,6 +198,7 @@ azkaban.JobListView = Backbone.View.extend({
$(el).append(ul);
return ul;
},
+
handleMenuExpand: function(li) {
var expandArrow = $(li).find("> a > .expandarrow");
var submenu = $(li).find("> ul");
@@ -196,6 +207,7 @@ azkaban.JobListView = Backbone.View.extend({
$(expandArrow).addClass("glyphicon-chevron-up");
$(submenu).slideDown();
},
+
handleMenuCollapse: function(li) {
var expandArrow = $(li).find("> a > .expandarrow");
var submenu = $(li).find("> ul");
@@ -204,6 +216,7 @@ azkaban.JobListView = Backbone.View.extend({
$(expandArrow).addClass("glyphicon-chevron-down");
$(submenu).slideUp();
},
+
handleToggleMenuExpand: function(evt) {
var expandarrow = evt.currentTarget;
var li = $(evt.currentTarget).closest("li.listElement");
@@ -218,12 +231,14 @@ azkaban.JobListView = Backbone.View.extend({
evt.stopImmediatePropagation();
},
+
handleContextMenuClick: function(evt) {
if (this.contextMenu) {
this.contextMenu(evt, this.model, evt.currentTarget.node);
return false;
}
},
+
handleJobClick: function(evt) {
console.log("Job clicked");
var li = $(evt.currentTarget).closest("li.listElement");
@@ -245,9 +260,11 @@ azkaban.JobListView = Backbone.View.extend({
this.model.set({"selected": node});
}
},
+
handleDisabledChange: function(evt) {
this.changeDisabled(this.model.get('data'));
},
+
changeDisabled: function(data) {
for (var i =0; i < data.nodes; ++i) {
var node = data.nodes[i];
@@ -262,6 +279,7 @@ azkaban.JobListView = Backbone.View.extend({
}
}
},
+
handleSelectionChange: function(evt) {
if (!this.model.hasChanged("selected")) {
return;
@@ -279,6 +297,7 @@ azkaban.JobListView = Backbone.View.extend({
this.propagateExpansion(current.listElement);
}
},
+
propagateExpansion: function(li) {
var li = $(li).parent().closest("li.listElement")[0];
if (li) {
@@ -286,9 +305,11 @@ azkaban.JobListView = Backbone.View.extend({
this.handleMenuExpand(li);
}
},
+
handleResetPanZoom: function(evt) {
this.model.trigger("resetPanZoom");
},
+
handleAutoPanZoom: function(evt) {
this.model.set({"autoPanZoom": $(evt.currentTarget).is(':checked')});
}