tez-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jeag...@apache.org
Subject git commit: TEZ-1600. Swimlanes View for Tez UI (jeagles)
Date Wed, 08 Oct 2014 23:40:13 GMT
Repository: tez
Updated Branches:
  refs/heads/TEZ-8 2f2739ddb -> c9fefa6f6


TEZ-1600. Swimlanes View for Tez UI (jeagles)


Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/c9fefa6f
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/c9fefa6f
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/c9fefa6f

Branch: refs/heads/TEZ-8
Commit: c9fefa6f626ad301486fe96616112192525882de
Parents: 2f2739d
Author: Jonathan Eagles <jeagles@gmail.com>
Authored: Wed Oct 8 18:39:42 2014 -0500
Committer: Jonathan Eagles <jeagles@gmail.com>
Committed: Wed Oct 8 18:39:42 2014 -0500

----------------------------------------------------------------------
 tez-ui/Gruntfile.js                             |   4 +-
 tez-ui/app/index.html                           |   3 +-
 tez-ui/app/scripts/app.js                       |   5 +-
 .../app/scripts/controllers/dag_controller.js   |   4 +-
 .../controllers/task_attempts_controller.js     |  35 ++++++
 tez-ui/app/scripts/helpers/ajax.js              |   6 +-
 .../app/scripts/mappers/task_attempt_mapper.js  |  38 ++++++
 .../app/scripts/models/TimelineRestAdapter.js   |  37 +++++-
 tez-ui/app/scripts/models/abstract_entity.js    |   5 +-
 tez-ui/app/scripts/models/task_attempt.js       |  40 +++++++
 tez-ui/app/scripts/router.js                    |  18 ++-
 tez-ui/app/scripts/views/swimlane_view.js       | 119 +++++++++++++++++++
 tez-ui/app/styles/swimlanes.css                 |  44 +++++++
 tez-ui/app/templates/dag/swimlane.hbs           |   5 +-
 tez-ui/bower.json                               |   2 +-
 15 files changed, 349 insertions(+), 16 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/Gruntfile.js
----------------------------------------------------------------------
diff --git a/tez-ui/Gruntfile.js b/tez-ui/Gruntfile.js
index 4e7fbde..a6d070a 100644
--- a/tez-ui/Gruntfile.js
+++ b/tez-ui/Gruntfile.js
@@ -74,7 +74,7 @@ module.exports = function (grunt) {
     },
     connect: {
       options: {
-        port: 9000,
+        port: 9001,
         // change this to '0.0.0.0' to access the server from outside
         hostname: 'localhost'
       },
@@ -368,7 +368,7 @@ module.exports = function (grunt) {
           cwd: "<%= yeoman.app %>/styles",
           src: ['styles/*.less', '**/*.less'],
           dest: ".tmp/styles",
-          ext: ".css" 
+          ext: ".css"
         }]
       },
       production: {

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/index.html
----------------------------------------------------------------------
diff --git a/tez-ui/app/index.html b/tez-ui/app/index.html
index 75ddf6d..1ee7859 100644
--- a/tez-ui/app/index.html
+++ b/tez-ui/app/index.html
@@ -23,6 +23,7 @@
 
     <!-- build:css styles/main.css -->
     <link rel="stylesheet" href="styles/main.css">
+    <link rel="stylesheet" href="styles/swimlanes.css">
     <link rel="stylesheet" href="bower_components/bootstrap/dist/css/bootstrap.css">
     <link rel="stylesheet" href="bower_components/ember-table/dist/ember-table.css">
     <link rel="stylesheet" href="bower_components/font-awesome/css/font-awesome.css">
@@ -54,7 +55,7 @@
     <script src="bower_components/jquery-mousewheel/jquery.mousewheel.js"></script>
     <script src="bower_components/ember-table/dist/ember-table.js"></script>
     <script src="bower_components/ember-addons.bs_for_ember/dist/js/bs-nav.min.js"></script>
-    <script src="bower_components/d3/d3.v2.js"></script>
+    <script src="bower_components/d3/d3.js"></script>
     <!-- endbuild -->
 
     <!-- build:js(.tmp) scripts/templates.js -->

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/app.js b/tez-ui/app/scripts/app.js
index a3d9d5c..d8b47d9 100644
--- a/tez-ui/app/scripts/app.js
+++ b/tez-ui/app/scripts/app.js
@@ -18,7 +18,7 @@
 
 var App = window.App = Em.Application.createWithMixins(Bootstrap, {
 	// Basic logging, e.g. "Transitioned into 'post'"
-  LOG_TRANSITIONS: true, 
+  LOG_TRANSITIONS: true,
 
   // Extremely detailed logging, highlighting every internal
   // step made while transitioning into a route, including
@@ -35,7 +35,7 @@ require('scripts/store');
 App.Helpers = Em.Namespace.create();
 App.Mappers = Em.Namespace.create();
 
-//TODO: initializer. 
+//TODO: initializer.
 
 /* Order and include */
 /* TODO: cleanup */
@@ -43,6 +43,7 @@ require('scripts/translations');
 require('scripts/mixins/*');
 require('scripts/helpers/*');
 require('scripts/models/**/*');
+require('scripts/views/**/*');
 require('scripts/mappers/server_data_mapper.js');
 require('scripts/mappers/**/*');
 require('scripts/controllers/**/*');

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/controllers/dag_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_controller.js b/tez-ui/app/scripts/controllers/dag_controller.js
index 6d601a2..1e2e4f2 100644
--- a/tez-ui/app/scripts/controllers/dag_controller.js
+++ b/tez-ui/app/scripts/controllers/dag_controller.js
@@ -34,7 +34,7 @@ App.DagController = Em.ObjectController.extend(App.Helpers.DisplayHelper,
{
 	childDisplayViews: [
 		Ember.Object.create({title: 'Details', linkTo: 'dag.index'}),
 		Ember.Object.create({title: 'Vertex', linkTo: 'dag.vertex'}),
-		Ember.Object.create({title: 'Dag View', linkTo: 'dag.swimlane'})
+		Ember.Object.create({title: 'Swimlane', linkTo: 'dag.swimlane'})
 	],
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/controllers/task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/task_attempts_controller.js b/tez-ui/app/scripts/controllers/task_attempts_controller.js
new file mode 100644
index 0000000..a49d54d
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/task_attempts_controller.js
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+App.DagSwimlaneController = Em.ArrayController.extend({
+  needs: "dag",
+  controllerName: "DagSwimlaneController",
+  pageTitle: "Task Attempts",
+  pageSubTitle: "All Task Attempts",
+  dag_id: Em.computed.alias('controllers.dag.id'),
+
+  getFilterParams: function(params) {
+    var dag_id = this.get('dag_id');
+    var filterParams = {};
+    if (dag_id) {
+      filterParams['primaryFilter'] = 'TEZ_DAG_ID:' + dag_id;
+    }
+
+    return filterParams;
+  },
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/helpers/ajax.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/helpers/ajax.js b/tez-ui/app/scripts/helpers/ajax.js
index 7b56135..f50401e 100644
--- a/tez-ui/app/scripts/helpers/ajax.js
+++ b/tez-ui/app/scripts/helpers/ajax.js
@@ -43,7 +43,11 @@ var urls = {
 
   load_vertex_details: {
     real: App.AtsBaseUrl + '/ws/v1/timeline/TEZ_VERTEX_ID/?primaryFilter=TEZ_DAG_ID:{dag_id}'
-  }
+  },
+
+  load_task_attempts: {
+    real: App.AtsBaseUrl + '/ws/v1/timeline/TEZ_TASK_ATTEMPT_ID/?primaryFilter=TEZ_DAG_ID:{dag_id}'
+  },
 };
 
 /**

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/mappers/task_attempt_mapper.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/mappers/task_attempt_mapper.js b/tez-ui/app/scripts/mappers/task_attempt_mapper.js
new file mode 100644
index 0000000..6e8877e
--- /dev/null
+++ b/tez-ui/app/scripts/mappers/task_attempt_mapper.js
@@ -0,0 +1,38 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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 jsonToTaskAttemptMap = {
+	id: 'entity',
+	startTime: 'otherinfo.startTime', //TODO: what is the difference between this and the one
in the otherinfo
+	endTime: 'otherinfo.endTime',
+	diagnostics: 'otherinfo.inProgressLogsURL',
+};
+
+App.Mappers.TaskAttempt = {
+	mapSingle : function(json) {
+		return Em.JsonMapper.map(json, jsonToTaskAttemptMap);
+	},
+
+	mapMany : function(json) {
+		if (Array.isArray(json.entities)) {
+			return json.entities.map(this.mapSingle);
+		}
+
+		return [];
+	}
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/models/TimelineRestAdapter.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/TimelineRestAdapter.js b/tez-ui/app/scripts/models/TimelineRestAdapter.js
index 2f82371..58d8f4b 100644
--- a/tez-ui/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/app/scripts/models/TimelineRestAdapter.js
@@ -1,6 +1,7 @@
 var typeToPathMap = {
 	dag: 'TEZ_DAG_ID',
-	vertex: 'TEZ_VERTEX_ID'
+	vertex: 'TEZ_VERTEX_ID',
+	taskAttempt: 'TEZ_TASK_ATTEMPT_ID',
 };
 
 App.TimelineRESTAdapter = DS.RESTAdapter.extend({
@@ -28,7 +29,7 @@ App.TimelineSerializer = DS.RESTSerializer.extend({
 	},
 
 	extractArray: function(store, primaryType, rawPayload) {
-		// restserializer expects a plural of the model but TimelineServer returns 
+		// restserializer expects a plural of the model but TimelineServer returns
 		// it in entities.
 		var payload = {};
 		payload[primaryType.typeKey.pluralize()] = rawPayload.entities;
@@ -122,3 +123,35 @@ App.CounterSerializer = DS.JSONSerializer.extend({
     };
   }
 });
+
+var timelineJsonToTaskAttemptMap = {
+  id: 'entity',
+  startTime: 'otherinfo.startTime',
+  endTime: 'otherinfo.endTime',
+  dagId: 'primaryfilters.dagId',
+  containerId: 'otherinfo.containerId',
+  status: 'otherinfo.status',
+};
+
+
+App.TaskAttemptSerializer = App.TimelineSerializer.extend({
+  normalizePayload: function(rawPayload){
+
+    // TODO - fake a containerId until it is present
+    var taskAttempts = rawPayload.taskAttempts;
+    for (var i = 0; i < taskAttempts.length; ++i) {
+      var taskAttempt = taskAttempts[i];
+      var inProgressLogsURL = taskAttempt.otherinfo.inProgressLogsURL;
+      var regex = /.*(container_.*?)\/.*/;
+      var match = regex.exec(inProgressLogsURL);
+      taskAttempt.otherinfo.containerId = match[1];
+      taskAttempt.primaryfilters.dagId = taskAttempt.primaryfilters.TEZ_DAG_ID[0];
+    }
+    return rawPayload;
+  },
+
+  normalize: function(type, hash, prop) {
+    var post = Em.JsonMapper.map(hash, timelineJsonToTaskAttemptMap);
+    return post;
+  },
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/models/abstract_entity.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/abstract_entity.js b/tez-ui/app/scripts/models/abstract_entity.js
index a3357ff..a3e7332 100644
--- a/tez-ui/app/scripts/models/abstract_entity.js
+++ b/tez-ui/app/scripts/models/abstract_entity.js
@@ -23,5 +23,6 @@ App.AbstractEntity = DS.Model.extend({
 App.EntityType = {
 	DAG: 'dag',
 	VERTEX: 'vertex',
-	TASK: 'task'
-};
\ No newline at end of file
+	TASK: 'task',
+  TASK_ATTEMPT: 'task_attempt',
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/models/task_attempt.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/task_attempt.js b/tez-ui/app/scripts/models/task_attempt.js
new file mode 100644
index 0000000..86cf230
--- /dev/null
+++ b/tez-ui/app/scripts/models/task_attempt.js
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with this
+ * work for additional information regarding copyright ownership. The ASF
+ * licenses this file to you 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.
+ */
+
+App.TaskAttempt = App.AbstractEntity.extend({
+
+  // start time of the entity
+  startTime: DS.attr('number'),
+
+  // end time of the entity
+  endTime: DS.attr('number'),
+
+	entityType: App.EntityType.TASK_ATTEMPT,
+
+  // dagId
+  dagId: DS.attr('string'),
+
+	// container
+	containerId: DS.attr('string'),
+
+  // status of the task attempt
+	status: DS.attr('string'),
+
+
+});
+
+App.TaskAttempt.FIXTURES = [];

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/router.js b/tez-ui/app/scripts/router.js
index 28e279d..ffac637 100644
--- a/tez-ui/app/scripts/router.js
+++ b/tez-ui/app/scripts/router.js
@@ -33,8 +33,8 @@ App.ApplicationRoute = Em.Route.extend({
 			return;
 			this.transitionTo('error').then(function(newRoute) {
 				newRoute.controller.set('err', {
-					target: transition.targetName, 
-					statusText: error.message, 
+					target: transition.targetName,
+					statusText: error.message,
 					responseText: error.stack
 				});
 				newRoute.controller.set('pageTitle', "Error");
@@ -86,3 +86,17 @@ App.DagRoute = Em.Route.extend({
 		this._super(controller, model);
 	}
 });
+
+App.DagSwimlaneRoute = Em.Route.extend({
+
+	model: function(params) {
+		var model = this.modelFor('dag');
+		var queryParams = {'primaryFilter': 'TEZ_DAG_ID:' + model.id};
+		this.store.unloadAll('task_attempt');
+		return this.store.findQuery('task_attempt', queryParams);
+	},
+
+	setupController: function(controller, model) {
+		this._super(controller, model);
+	}
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/scripts/views/swimlane_view.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/views/swimlane_view.js b/tez-ui/app/scripts/views/swimlane_view.js
new file mode 100644
index 0000000..9420e18
--- /dev/null
+++ b/tez-ui/app/scripts/views/swimlane_view.js
@@ -0,0 +1,119 @@
+App.SwimlanesView = Ember.View.extend({
+
+  didInsertElement: function() {
+    var task_attempts = this.get("content");
+    var timeBegin = d3.min(task_attempts, function (d) { return d.get('startTime') });
+    var timeEnd = d3.max(task_attempts, function (d) { return d.get('endTime') });
+    var containers = d3.set(task_attempts.map(function (d) {return d.get('containerId')})).values().sort();
+    var laneLength = containers.length;
+
+    var margin = {top: 20, right: 15, bottom: 15, left: 280};
+    var width = 960 - margin.left - margin.right;
+    var height = 500 - margin.top - margin.bottom;
+    var laneHeight = 18;
+    var miniHeight = laneLength * laneHeight;
+
+    //scales
+    var x = d3.scale.linear()
+    .range([0, width])
+    .domain([timeBegin, timeEnd]);
+
+    var y = d3.scale.ordinal()
+    .domain(containers)
+    .rangeRoundBands([0, miniHeight], .20);
+
+    var xAxis = d3.svg.axis()
+    .scale(x)
+    .orient("bottom")
+    .tickSize(0)
+    .tickFormat(function(d) { return (d - timeBegin)/1000; });
+
+    var yAxis = d3.svg.axis()
+    .scale(y)
+    .tickSize(0)
+    .orient("left");
+
+    $('#swimlane').html('');
+    var div = d3.select("#swimlane")
+    .append("div") // declare the tooltip div
+    .attr("class", "tooltip") // apply the 'tooltip' class
+    .style("opacity", 0);
+
+    var svg = d3.select("#swimlane")
+    .append("svg")
+    .attr("width", width + margin.left + margin.right)
+    .attr("height", height + margin.top + margin.bottom)
+    .attr("class", "svg");
+
+    var mini = svg.append("g")
+    .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
+    .attr("class", "mini");
+
+    mini.append("g")
+    .attr("class", "y axis")
+    .call(yAxis)
+    .selectAll("text")
+    .style("text-anchor", "end");
+
+    mini.append("g")
+    .attr("class", "x axis")
+    .attr("transform", "translate(0," + miniHeight + ")")
+    .call(xAxis)
+    .selectAll("text")
+    .style("text-anchor", "end")
+    .attr("transform", "rotate(-90)" );
+
+    // draw container rectangles
+    mini.append("g").selectAll("container")
+    .data(containers)
+    .enter().append("a").attr("xlink:href","file:///Users/jeagles/myember/")
+    .append("rect")
+    .attr("class", "container")
+    .attr("x", 0)
+    .attr("y", function(d) {return y(d);})
+    .attr("width", width)
+    .attr("rx", 6)
+    .attr("height", y.rangeBand());
+
+    // draw task attempt rectangles
+    mini.append("g").selectAll("task_attempt")
+    .data(task_attempts)
+    .enter().append("rect")
+    .attr("class", function(d) {return "task_attempt";})
+    .attr("x", function(d) {return x(d.get('startTime'));})
+    .attr("y", function(d) {return y(d.get('containerId'));})
+    .attr("width", function(d) {return x(d.get('endTime')) - x(d.get('startTime'));})
+    .attr("rx", 6)
+    .attr("height", y.rangeBand())
+    // Tooltip stuff after this
+    .on("mouseover", function(d) {
+      div.transition()
+      .duration(500)
+      .style("opacity", 0);
+      div.transition()
+      .duration(200)
+      .style("opacity", .9);
+      div .html(
+        // TODO: Replace with correct route to task attempt
+        '<a href= "/task_attempt/' + d.get('id') + '">' +
+        d.get('id') +
+          "</a>" +
+          "<br/>Start: " + moment(d.get('startTime')).format() +
+          "<br/>End: " + moment(d.get('endTime')).format())
+        .style("left", (d3.event.pageX) + "px")
+        .style("top", (d3.event.pageY - 28) + "px");
+    });
+
+    /*
+    // TODO: task attempt labels - draw labels if they fit
+    mini.append("g").selectAll("task_attempt_label")
+    .data(task_attempts)
+    .enter().append("text")
+    .text(function(d) {return d.get('id');})
+    .attr("x", function(d) {return x(d.get('startTime'));})
+    .attr("y", function(d) {return y(d.get('containerId'));})
+    .attr("dy", ".5ex");
+    */
+
+  },
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/styles/swimlanes.css
----------------------------------------------------------------------
diff --git a/tez-ui/app/styles/swimlanes.css b/tez-ui/app/styles/swimlanes.css
new file mode 100644
index 0000000..ad8a1d0
--- /dev/null
+++ b/tez-ui/app/styles/swimlanes.css
@@ -0,0 +1,44 @@
+.svg {
+  shape-rendering: crispEdges;
+}
+
+.axis {
+  font: 10px sans-serif;
+}
+
+.x.axis path {
+  display: none;
+}
+
+.axis line {
+  fill: none;
+  stroke: #000;
+  shape-rendering: crispEdges;
+}
+
+.mini text {
+  font: 12px sans-serif;
+  fill: black;
+}
+
+.container {
+  fill: lightblue;
+  stroke-width: 6;
+}
+
+.task_attempt {
+  fill: slategray;
+  stroke-width: 6;
+}
+
+div.tooltip {
+  position: absolute;
+  text-align: left;
+  width: 270px;
+  height: 48px;
+  padding: 6px;
+  font: 12px sans-serif;
+  background: lightsteelblue;
+  border: 0px;
+  border-radius: 8px;
+}

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/app/templates/dag/swimlane.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag/swimlane.hbs b/tez-ui/app/templates/dag/swimlane.hbs
index e2a733f..dd81832 100644
--- a/tez-ui/app/templates/dag/swimlane.hbs
+++ b/tez-ui/app/templates/dag/swimlane.hbs
@@ -1 +1,4 @@
-Placeholder for swimlanes
\ No newline at end of file
+<div id="swimlane">
+{{#view App.SwimlanesView contentBinding="controller.model.content"}}
+{{/view}}
+</div>

http://git-wip-us.apache.org/repos/asf/tez/blob/c9fefa6f/tez-ui/bower.json
----------------------------------------------------------------------
diff --git a/tez-ui/bower.json b/tez-ui/bower.json
index 108e92b..efec4ec 100644
--- a/tez-ui/bower.json
+++ b/tez-ui/bower.json
@@ -9,7 +9,7 @@
     "bootstrap": "3.0.0",
     "ember-json-mapper": "master",
     "jquery-ui": ">=1.11",
-    "d3": "2.10.2",
+    "d3": "3.4.11",
     "ember-addons.bs_for_ember": "~0.7.0",
     "ember-table": "~0.2.2"
   },


Mime
View raw message