You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by je...@apache.org on 2014/12/10 04:33:37 UTC

[14/53] tez git commit: TEZ-1603. Vertex View for Tez UI. (Sreenath Somarajapuram via hitesh)

TEZ-1603. Vertex View for Tez UI. (Sreenath Somarajapuram via hitesh)


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

Branch: refs/heads/master
Commit: ce6d17a91098303d6f3988d2322b8a93c2c80a89
Parents: 44e5579
Author: Hitesh Shah <hi...@apache.org>
Authored: Mon Oct 27 14:48:12 2014 -0700
Committer: Hitesh Shah <hi...@apache.org>
Committed: Mon Oct 27 14:48:12 2014 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +
 .../scripts/controllers/vertex_controller.js    |  40 +++++++
 .../controllers/vertex_index_controller.js      |  26 +++++
 .../controllers/vertex_tasks_controller.js      | 106 +++++++++++++++++++
 tez-ui/app/scripts/mixins/paginated_content.js  |   3 +-
 .../app/scripts/models/TimelineRestAdapter.js   |  12 ++-
 tez-ui/app/scripts/models/dag.js                |  12 +++
 tez-ui/app/scripts/router.js                    |  33 +++++-
 tez-ui/app/templates/vertex.hbs                 |  50 +++++++++
 tez-ui/app/templates/vertex/counters.hbs        |  21 ++++
 tez-ui/app/templates/vertex/index.hbs           |  81 ++++++++++++++
 tez-ui/app/templates/vertex/swimlane.hbs        |  22 ++++
 tez-ui/app/templates/vertex/tasks.hbs           |  46 ++++++++
 13 files changed, 449 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index e849248..fcbadcf 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,8 @@ ALL CHANGES:
   TEZ-1634. Fix compressed IFile shuffle errors
   TEZ-1615. Skeleton framework for Tez UI
   TEZ-1604. Task View for Tez UI
+  TEZ-1603. Vertex View for Tez UI.
+
 
 Release 0.5.2: Unreleased
 

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_controller.js b/tez-ui/app/scripts/controllers/vertex_controller.js
new file mode 100644
index 0000000..f5c7ef4
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_controller.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.VertexController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
+  controllerName: 'VertexController',
+
+  pageTitle: 'Vertex',
+
+  loading: true,
+
+  updateLoading: function() {
+    this.set('loading', false);
+  }.observes('content'),
+
+  pageSubTitle: function() {
+    return this.get('id');
+  }.property('id'),
+
+  childDisplayViews: [
+    Ember.Object.create({title: 'Details', linkTo: 'vertex.index'}),
+    Ember.Object.create({title: 'Tasks', linkTo: 'vertex.tasks'}),
+    Ember.Object.create({title: 'Counters', linkTo: 'vertex.counters'}),
+    Ember.Object.create({title: 'Swimlane', linkTo: 'vertex.swimlane'}),
+  ],
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_index_controller.js b/tez-ui/app/scripts/controllers/vertex_index_controller.js
new file mode 100644
index 0000000..c1cf234
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_index_controller.js
@@ -0,0 +1,26 @@
+/**
+ * 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.VertexIndexController = Em.ObjectController.extend({
+  controllerName: 'VertexIndexController',
+
+  //TODO: TEZ-1705 : Create a parent class and move this function there to avoid duplication.
+  iconStatus: function() {
+    return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
+  }.property('id', 'status', 'counterGroups'),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_tasks_controller.js b/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
new file mode 100644
index 0000000..05b501c
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
@@ -0,0 +1,106 @@
+/**
+ * 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.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+  reloadData: function() {
+    this.loadEntities();
+  }.observes('id'),
+
+  // Required by the PaginatedContentMixin
+  parentEntityType: 'vertex',
+  childEntityType: 'task',
+
+  filterValues: {},
+
+  reloadWhenFiltersChange: function() {
+    var filters = {
+      id: null,
+      primary: {},
+      secondary: {}
+    };
+    var fv = this.filterValues;
+    filters.primary.TEZ_VERTEX_ID = fv.vertex_id;
+    filters.secondary.status = fv.status;
+    this.setFiltersAndLoadEntities(filters);
+  }.observes('filterValues.task_id', 'filterValues.vertex_id', 'filterValues.status'),
+
+  columns: function() {
+    var idCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Task ID',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          "{{#link-to 'task' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+      }),
+      contentPath: 'id',
+    });
+
+    var vertexCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Vertex ID',
+      filterID: 'vertex_id',
+      contentPath: 'vertexID',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          "{{#link-to 'vertex' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+      }),
+    });
+
+    var startTimeCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Submission Time',
+      getCellContent: function(row) {
+        return App.Helpers.date.dateFormat(row.get('startTime'));
+      }
+    });
+
+    var endTimeCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'End Time',
+      getCellContent: function(row) {
+        return App.Helpers.date.dateFormat(row.get('endTime'));
+      }
+    });
+
+    var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
+      textAlign: 'text-align-left',
+      headerCellName: 'Status',
+      filterID: 'status',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          '<span class="ember-table-content">&nbsp;\
+          <i {{bind-attr class=":task-status view.cellContent.statusIcon"}}></i>\
+          &nbsp;&nbsp;{{view.cellContent.status}}</span>')
+      }),
+      getCellContent: function(row) {
+        return {
+          status: row.get('status'),
+          statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
+        };
+      }
+    });
+
+    var nodeCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Node',
+      contentPath: 'node'
+    });
+
+    return [idCol, vertexCol, startTimeCol, endTimeCol, statusCol];
+  }.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/mixins/paginated_content.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/mixins/paginated_content.js b/tez-ui/app/scripts/mixins/paginated_content.js
index 7288759..d34c90e 100644
--- a/tez-ui/app/scripts/mixins/paginated_content.js
+++ b/tez-ui/app/scripts/mixins/paginated_content.js
@@ -18,6 +18,7 @@
 var modelToATSType = {
 	dag: 'TEZ_DAG_ID',
 	task: 'TEZ_TASK_ID',
+	vertex: 'TEZ_VERTEX_ID',
 	taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
 };
 
@@ -172,4 +173,4 @@ App.PaginatedContentMixin = Em.Mixin.create({
 
 		return params;
 	},
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/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 43353ba..e753b5e 100644
--- a/tez-ui/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/app/scripts/models/TimelineRestAdapter.js
@@ -275,12 +275,18 @@ var timelineJsonToVertexMap = {
   id: 'entity',
   name: 'otherinfo.vertexName',
   dagID: 'primaryfilters.TEZ_DAG_ID.0',
+  counterGroups: 'counterGroups',
+
   startTime: 'otherinfo.startTime',
   endTime: 'otherinfo.endTime',
+
   status: 'otherinfo.status',
   diagnostics: 'otherinfo.diagnostics',
-  counterGroups: 'counterGroups',
-  numTasks: 'otherinfo.numTasks'
+
+  failedTasks: 'otherinfo.numFailedTasks',
+  sucessfulTasks: 'otherinfo.numSucceededTasks',
+  numTasks: 'otherinfo.numTasks',
+  killedTasks: 'otherinfo.numKilledTasks',
 };
 
 App.VertexSerializer = App.TimelineSerializer.extend({
@@ -313,7 +319,7 @@ App.VertexSerializer = App.TimelineSerializer.extend({
       }, this);
       
       // delete so that we dont hang on to the json data.
-      delete rawPayload.vertex;
+      delete rawPayload.vertices;
 
       return normalizedPayload;
     } else {

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/dag.js b/tez-ui/app/scripts/models/dag.js
index 3fc9c83..1bd3182 100644
--- a/tez-ui/app/scripts/models/dag.js
+++ b/tez-ui/app/scripts/models/dag.js
@@ -89,6 +89,7 @@ App.Vertex = DS.Model.extend({
   name: DS.attr('string'),
 
   dag: DS.belongsTo('dag'),
+  dagID: DS.attr('string'),
 
   /**
    * State of this vertex. Should be one of constants defined in
@@ -146,6 +147,17 @@ App.Vertex = DS.Model.extend({
    */
   numTasks: DS.attr('number'),
 
+  name: DS.attr('string'),
+
+  failedTasks: DS.attr('number'),
+  sucessfulTasks: DS.attr('number'),
+  numTasks: DS.attr('number'),
+  killedTasks: DS.attr('number'),
+
+  diagnostics: DS.attr('string'),
+
+  counterGroups: DS.hasMany('counterGroup'),
+
   tasksNumber: function () {
     return this.getWithDefault('tasksCount', 0);
   }.property('tasksCount'),

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/router.js b/tez-ui/app/scripts/router.js
index 3540495..0e800ac 100644
--- a/tez-ui/app/scripts/router.js
+++ b/tez-ui/app/scripts/router.js
@@ -24,7 +24,13 @@ App.Router.map(function() {
 		this.route('counters'),
 		this.route('swimlane')
 	});
-	this.resource('vertex', {path: '/vertex/:vertex_id'});
+
+  this.resource('vertex', {path: '/vertex/:vertex_id'}, function(){
+    this.route('tasks');
+    this.route('counters');
+    this.route('details');
+    this.route('swimlane');
+  });
 	
 	this.resource('tasks', {path: '/tasks/:dag_id'});
 	this.resource('task', {path: '/task/:task_id'}, function(){
@@ -141,3 +147,28 @@ App.TaskRoute = Em.Route.extend({
 		this._super(controller, model);
 	}
 });
+
+App.VertexRoute = Em.Route.extend({
+	model: function(params) {
+		return this.store.find('vertex', params.vertex_id);
+	},
+
+	setupController: function(controller, model) {
+		this._super(controller, model);
+	}
+});
+
+App.VertexSwimlaneRoute = Em.Route.extend({
+  model: function(params) {
+    var model = this.modelFor('vertex');
+    var queryParams = {'primaryFilter': 'TEZ_DAG_ID:' + model.get('dagID') };
+    this.store.unloadAll('task_attempt');
+    return this.store.filter('task_attempt', queryParams, function(ta) {
+      return ta.get('vertexID') == model.id;
+    });
+  },
+
+  setupController: function(controller, model) {
+    this._super(controller, model);
+  }
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex.hbs b/tez-ui/app/templates/vertex.hbs
new file mode 100644
index 0000000..f083e2c
--- /dev/null
+++ b/tez-ui/app/templates/vertex.hbs
@@ -0,0 +1,50 @@
+{{!
+* 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.
+}}
+
+{{partial "utils/pageHeader"}}
+{{#unless loading}}
+  <div class='margin-small-horizontal'>
+    {{#link-to 'dags'}}
+      <i class='fa-arrow-circle-left fa fa-2x'>
+        <span style='font-size: 85%'>&nbsp;Dags</span>
+      </i>
+    {{/link-to}}
+  </div>
+  <div class='type-table fill-full '>
+    <div class='align-left'>
+      <table class='detail-list'>
+        <tbody>
+          <tr>
+            <td>{{t common.id}}</td>
+            <td>{{id}}</td>
+          </tr>
+          <tr>
+            <td>DAG ID</td>
+            <td>{{dagID}}</td>
+          </tr>
+        </tbody>
+      </table>
+    </div>
+    <div class='pill-container align-right'>
+      {{bs-pills contentBinding='childDisplayViews' selectedBinding='childDisplayViewSelected' size='lg'}}
+    </div>
+  </div>
+  {{outlet}}
+{{else}}
+    {{partial 'utils/loadingSpinner'}}
+{{/unless}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/counters.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/counters.hbs b/tez-ui/app/templates/vertex/counters.hbs
new file mode 100644
index 0000000..4c082e1
--- /dev/null
+++ b/tez-ui/app/templates/vertex/counters.hbs
@@ -0,0 +1,21 @@
+{{!
+* 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.
+}}
+
+<div class='table-container margin-medium' style='width: 50%;'>
+  {{counter-table-component data=counterGroups}}
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/index.hbs b/tez-ui/app/templates/vertex/index.hbs
new file mode 100644
index 0000000..ce21749
--- /dev/null
+++ b/tez-ui/app/templates/vertex/index.hbs
@@ -0,0 +1,81 @@
+{{!
+* 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.
+}}
+
+<div class='type-table fill-full margin-small-horizontal'>
+  <div class='align-left'>
+    <table class='detail-list'>
+      <tbody>
+        <tr>
+          <td>Vertex Name</td>
+          <td>
+            {{name}}
+          </td>
+        </tr>
+        <tr>
+          <td>{{t common.status}}</td>
+          <td>
+            <i {{bind-attr class=':task-status iconStatus'}}></i>
+            {{status}}
+          </td>
+        </tr>
+        <tr>
+          <td>Total Tasks</td>
+          <td>{{numTasks}}</td>
+        </tr>
+        <tr>
+          <td>Successful Tasks</td>
+          <td>{{sucessfulTasks}}</td>
+        </tr>
+        <tr>
+          <td>Failed Tasks</td>
+          <td>
+            {{failedTasks}}
+          </td>
+        </tr>
+        <tr>
+          <td>Killed Tasks</td>
+          <td>{{killedTasks}}</td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+  <div class='align-right'>
+    <table class='detail-list'>
+      <tbody>
+        <tr>
+          <td>{{t common.time.start}}</td>
+          <td>{{formatUnixTimestamp startTime}}</td>
+        </tr>
+        <tr>
+          <td>{{t common.time.end}}</td>
+          <td>{{formatUnixTimestamp endTime}}</td>
+        </tr>
+        <tr>
+          <td>{{t common.time.duration}}</td>
+          <td>{{formatDuration startTime endTime}}</td>
+        </tr>
+      </tbody>
+    </table>
+  </div>
+</div>
+
+{{#if diagnostics}}
+  {{#bs-panel heading="Diagnostics" collapsible=false dismiss=false type='danger'}}
+    {{formatDiagnostics diagnostics}}
+  {{/bs-panel}}
+{{/if}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/swimlane.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/swimlane.hbs b/tez-ui/app/templates/vertex/swimlane.hbs
new file mode 100644
index 0000000..2745e08
--- /dev/null
+++ b/tez-ui/app/templates/vertex/swimlane.hbs
@@ -0,0 +1,22 @@
+{{!
+* 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.
+}}
+
+<div id="swimlane">
+  {{#view App.SwimlanesView contentBinding="controller.model.content"}}
+  {{/view}}
+</div>

http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/tasks.hbs b/tez-ui/app/templates/vertex/tasks.hbs
new file mode 100644
index 0000000..eac99a1
--- /dev/null
+++ b/tez-ui/app/templates/vertex/tasks.hbs
@@ -0,0 +1,46 @@
+{{!
+* 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.
+}}
+
+{{#unless loading}}
+  <div class='margin-small'>
+    <span class='align-left'>
+      {{page-nav-component
+        hasPrev=hasPrev
+        hasNext=hasNext
+        navNext='navigateNext'
+        navPrev='navigatePrev'
+        navFirst='navigateFirst'
+      }}
+    </span>
+    <div class='align-clear'> </div>
+  </div>
+
+  <div class='table-container'>
+  {{extended-table-component
+    hasFooter=false
+    enableContentSelection=true
+    columnsBinding="columns"
+    contentBinding="sortedContent"
+    forceFillColumns=true
+    filtersBinding='filterValues'
+    hasFilter=true
+  }}
+  </div>
+{{else}}
+  {{partial 'utils/loadingSpinner'}}
+{{/unless}}
\ No newline at end of file