tez-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jeag...@apache.org
Subject [13/53] tez git commit: TEZ-1604. Task View for Tez UI (Prakash Ramachandran via jeagles)
Date Wed, 10 Dec 2014 03:33:36 GMT
TEZ-1604. Task View for Tez UI (Prakash Ramachandran via jeagles)


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

Branch: refs/heads/master
Commit: 44e5579e29137708571dc9591f9db8090881aecd
Parents: f6d8517
Author: Jonathan Eagles <jeagles@gmail.com>
Authored: Thu Oct 23 10:54:40 2014 -0500
Committer: Jonathan Eagles <jeagles@gmail.com>
Committed: Thu Oct 23 10:54:40 2014 -0500

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 tez-ui/app/scripts/components/extended-table.js | 219 +++++++++++++++++++
 tez-ui/app/scripts/components/tasks-view.js     |   4 -
 .../app/scripts/controllers/dag_controller.js   |   2 +
 tez-ui/app/scripts/controllers/dag_counters.js  |  23 --
 .../scripts/controllers/dag_index_controller.js |   3 -
 .../controllers/dag_swimlane_controller.js      |  35 +++
 tez-ui/app/scripts/controllers/dag_tasks.js     | 111 ++++++++++
 tez-ui/app/scripts/controllers/dag_vertices.js  | 103 +++++++++
 .../app/scripts/controllers/dags_controller.js  |  25 ++-
 .../controllers/task_attempts_controller.js     |  35 ---
 .../app/scripts/controllers/task_controller.js  |   1 +
 .../controllers/task_index_controller.js        |   3 -
 .../task_task_attempts_controller.js            | 123 +++++++++++
 .../app/scripts/mappers/task_attempt_mapper.js  |  38 ----
 tez-ui/app/scripts/mixins/paginated_content.js  | 175 +++++++++++++++
 .../app/scripts/models/TimelineRestAdapter.js   |  71 +++++-
 tez-ui/app/scripts/models/dag.js                |  36 +--
 tez-ui/app/scripts/models/task_attempt.js       |   1 +
 tez-ui/app/scripts/router.js                    |   6 +-
 tez-ui/app/scripts/store.js                     |  21 --
 tez-ui/app/scripts/views/show_tasks_view.js     |  81 -------
 tez-ui/app/scripts/views/tasks_view.js          |  23 --
 tez-ui/app/styles/main.less                     |  22 ++
 .../components/extended-table/extable.hbs       |  12 +
 .../components/extended-table/filter-cell.hbs   |   9 +
 .../extended-table/filter-container.hbs         |  15 ++
 .../components/extended-table/filter-row.hbs    |   5 +
 tez-ui/app/templates/dag.hbs                    |   8 -
 tez-ui/app/templates/dag/index.hbs              |   2 -
 tez-ui/app/templates/dag/tasks.hbs              |  29 +++
 tez-ui/app/templates/dag/vertex.hbs             |   1 -
 tez-ui/app/templates/dag/vertices.hbs           |  28 +++
 tez-ui/app/templates/task/attempts.hbs          |  28 +++
 tez-ui/app/templates/task/index.hbs             |   2 -
 tez-ui/app/templates/taskAttempt/index.hbs      |  43 ++++
 tez-ui/app/templates/views/show_tasks.hbs       |  38 ----
 37 files changed, 1071 insertions(+), 311 deletions(-)
----------------------------------------------------------------------


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

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/components/extended-table.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/components/extended-table.js b/tez-ui/app/scripts/components/extended-table.js
new file mode 100644
index 0000000..48d11bf
--- /dev/null
+++ b/tez-ui/app/scripts/components/extended-table.js
@@ -0,0 +1,219 @@
+/**
+ * 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.ExTable = Ember.Namespace.create();
+
+//TODO: fix top calculation in FooterTableContainer
+
+App.ExTable.FilterField = Em.TextField.extend({
+	classNames: ['filter'],
+  classNameBindings: ['isPopulated','isInputDirty:input-dirty'],
+  type: 'search',
+  results: 1,
+  attributeBindings: ['autofocus', 'results'],
+  valueBinding: Em.Binding.oneWay('filterValue'),
+  isPopulated: function() {
+  	return !Em.isEmpty(this.get('value'));
+  }.property('value'),
+  insertNewline: function(event) {
+  	if (this.get('isInputDirty')) {
+  		this.set('filterValue', this.get('value'))
+  	}
+  },
+  cancel: function() {
+  	//TODO: ignoring cancel for now. user needs to press enter.
+  	//this.set('filterValue', this.get('value'))
+  },
+  /* TODO: remove this
+  doUpdateFilter: function(action) {
+  	if (action) {
+  		this.get('parentView.controller').send(action, this.get('parentView.content'));
+  	}
+  },*/
+  isInputDirty: function() {
+  	return $.trim(this.get('value')) != $.trim(this.get('filterValue'));
+  }.property('value', 'filterValue')
+});
+
+App.ExTable.FilterRow = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, {
+  templateName: 'components/extended-table/filter-row',
+  classNames: ['ember-table-table-row', 'ember-table-header-row'],
+  styleBindings: ['width'],
+  columns: Ember.computed.alias('content'),
+  width: Ember.computed.alias('controller._rowWidth'),
+  scrollLeft: Ember.computed.alias('controller._tableScrollLeft'),
+  onScrollLeftDidChange: function() {
+    return this.$().scrollLeft(this.get('scrollLeft'));
+  }.observes('scrollLeft'),
+  onScroll: function(event) {
+    this.set('scrollLeft', event.target.scrollLeft);
+    return event.preventDefault();
+  }
+});
+
+App.ExTable.FilterBlock = Ember.Table.TableBlock.extend({
+  classNames: ['ember-table-header-block'],
+  itemViewClass: 'App.ExTable.FilterRow',
+  content: function() {
+    return [this.get('columns')];
+  }.property('columns')
+});
+
+App.ExTable.FilterTableContainer = Ember.Table.TableContainer.extend(Ember.Table.ShowHorizontalScrollMixin, {
+  templateName: 'components/extended-table/filter-container',
+  classNames: ['ember-table-table-container', 'ember-table-fixed-table-container', 'ember-table-header-container'],
+  height: Ember.computed.alias('controller._filterHeight'),
+  width: Ember.computed.alias('controller._tableContainerWidth')
+});
+
+App.ExTable.FilterCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixin, {
+  templateName: 'components/extended-table/filter-cell',
+  classNames: ['ember-table-cell', 'ember-table-header-cell'],
+  classNameBindings: ['column.textAlign'],
+  styleBindings: ['width', 'height'],
+ 	column: Ember.computed.alias('content'),
+  width: Ember.computed.alias('column.columnWidth'),
+  height: function() {
+  	return this.get('controller._filterHeight');
+  }.property('controller._filterHeight'),
+  isPopulated: function() {//TODO: remove
+  	return true;
+  }.property()
+  //TODO: handle resizing if required.
+});
+
+App.ExTable.ColumnDefinition = Ember.Table.ColumnDefinition.extend({
+	init: function() {
+		var columnFilterValueBinding = Em.Binding.from('columnFilterValue').to('controller.filters.' + this.get('filterID'));
+		columnFilterValueBinding.connect(this);
+	},
+	filterCellView: 'App.ExTable.FilterCell',
+  filterCellViewClass: Ember.computed.alias('filterCellView'),
+  filterID: null,
+  isPopulated: function() {
+  	return !Em.isEmpty(this.get('columnFilterValue'));
+  }.property('columnFilterValue'),
+});
+
+App.ExTable.TableComponent = Ember.Table.EmberTableComponent.extend({
+	layoutName: 'components/extended-table/extable',
+	filters: {},
+
+	hasFilter: true,
+	minFilterHeight: 30, //TODO: less changes
+
+	actions: {
+		updateFilter: function(columnDef) {
+			var filterID = columnDef.get('filterID');
+			filterID = filterID || columnDef.get('headerCellName').underscore();
+			var filterValue = $.trim(columnDef.get('columnFilterValue'));
+			if (filterValue === this.filters[filterID]) {
+				return; // nothing to do.
+			}
+			if (Em.empty(filterValue)) {
+				delete this.filters[filterID];
+			} else {
+				//this.filters[filterID] = filterValue;
+				this.get('filters').set(filterID, filterValue);
+			}
+			if (this.get('onFilterUpdated')) {
+				this.sendAction('onFilterUpdated', this.filters);
+			}
+		},
+
+		removeFilter: function(columnDef) {
+			var filterID = columnDef.get('filterID');
+			if (!this.filters[filterID]) {
+				return;
+			}
+			delete this.filters[filterID];
+			columnDef.set('columnFilterValue', null);
+			if (this.get('onFilterUpdated')) {
+				this.sendAction('onFilterUpdated', this.filters);
+			}
+		}
+	},
+
+	// private variables
+	// Dynamic filter height that adjusts according to the filter content height
+	_contentFilterHeight: null,
+  _filterHeight: function() {
+    var minHeight = this.get('minFilterHeight');
+    var contentFilterHeight = this.get('_contentFilterHeight');
+    if (contentFilterHeight < minHeight) {
+      return minHeight;
+    } else {
+      return contentFilterHeight;
+    }
+  }.property('_contentFilterHeight', 'minFilterHeight'),
+
+	// some of these below are private functions extend. however to add the filterrow we need them.
+	// tables-container height adjusts to the content height
+	_tablesContainerHeight: function() {
+    var contentHeight, height;
+    height = this.get('_height');
+    contentHeight = this.get('_tableContentHeight') + this.get('_headerHeight') + this.get('_footerHeight') 
+    	+ this.get('_filterHeight');
+    if (contentHeight < height) {
+      return contentHeight;
+    } else {
+      return height;
+    }
+  }.property('_height', '_tableContentHeight', '_headerHeight', '_footerHeight', '_filterHeight'),
+
+  _bodyHeight: function() {
+    var bodyHeight;
+    bodyHeight = this.get('_tablesContainerHeight');
+    if (this.get('hasHeader')) {
+      bodyHeight -= this.get('_headerHeight');
+    }
+    if (this.get('hasFilter')) { 
+      bodyHeight -= this.get('_filterHeight');
+    }
+    if (this.get('hasFooter')) {
+      bodyHeight -= this.get('footerHeight');
+    }
+    return bodyHeight;
+  }.property('_tablesContainerHeight', '_hasHorizontalScrollbar', '_headerHeight', 'footerHeight', '_filterHeight',
+  	'hasHeader', 'hasFooter', 'hasFilter'), 
+
+  _hasVerticalScrollbar: function() {
+    var contentHeight, height;
+    height = this.get('_height');
+    contentHeight = this.get('_tableContentHeight') + this.get('_headerHeight') + this.get('_footerHeight') 
+    	+ this.get('_filterHeight');
+    if (height < contentHeight) {
+      return true;
+    } else {
+      return false;
+    }
+  }.property('_height', '_tableContentHeight', '_headerHeight', '_footerHeight', '_filterHeight'),
+
+  _tableContentHeight: function() {
+    return this.get('rowHeight') * this.get('bodyContent.length');
+  }.property('rowHeight', 'bodyContent.length')
+});
+
+App.ExTable.FilterColumnMixin = Ember.Mixin.create({
+		isFilterable: true,
+		filterPresent: function() {
+			return !Em.isEmpty(this.get('columnFilterValue'));
+		}.property('columnFilterValue'),
+});
+
+Ember.Handlebars.helper('extended-table-component', App.ExTable.TableComponent);
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/components/tasks-view.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/components/tasks-view.js b/tez-ui/app/scripts/components/tasks-view.js
deleted file mode 100644
index 494dcfa..0000000
--- a/tez-ui/app/scripts/components/tasks-view.js
+++ /dev/null
@@ -1,4 +0,0 @@
-App.ShowTasksComponent = Ember.Component.extend({
-	foo: function() {
-	}.on('didInsertElement')
-});

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/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 414bc1d..bbf8e12 100644
--- a/tez-ui/app/scripts/controllers/dag_controller.js
+++ b/tez-ui/app/scripts/controllers/dag_controller.js
@@ -33,6 +33,8 @@ App.DagController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
 
 	childDisplayViews: [
 		Ember.Object.create({title: 'Details', linkTo: 'dag.index'}),
+		Ember.Object.create({title: 'Vertices', linkTo: 'dag.vertices'}),
+		Ember.Object.create({title: 'Tasks', linkTo: 'dag.tasks'}),
 		Ember.Object.create({title: 'Counters', linkTo: 'dag.counters'}),
 		Ember.Object.create({title: 'Swimlane', linkTo: 'dag.swimlane'})
 	],

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/dag_counters.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_counters.js b/tez-ui/app/scripts/controllers/dag_counters.js
deleted file mode 100644
index 80aee92..0000000
--- a/tez-ui/app/scripts/controllers/dag_counters.js
+++ /dev/null
@@ -1,23 +0,0 @@
-/**
- * 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.
- */
-
- //TODO: watch individual counters.
-/*App.DagCountersController = Em.ObjectController.extend({
-	controllerName: 'DagIndexController',
-
-});*/
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/dag_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_index_controller.js b/tez-ui/app/scripts/controllers/dag_index_controller.js
index c9cc99e..6837c57 100644
--- a/tez-ui/app/scripts/controllers/dag_index_controller.js
+++ b/tez-ui/app/scripts/controllers/dag_index_controller.js
@@ -16,8 +16,6 @@
  * limitations under the License.
  */
 
- require('scripts/controllers/show_tasks_view_controller');
-
  //TODO: watch individual counters.
 App.DagIndexController = Em.ObjectController.extend({
 	controllerName: 'DagIndexController',
@@ -56,5 +54,4 @@ App.DagIndexController = Em.ObjectController.extend({
 		}
 	},
 
-	showTasksViewController: App.ShowTasksViewController.create()
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/dag_swimlane_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_swimlane_controller.js b/tez-ui/app/scripts/controllers/dag_swimlane_controller.js
new file mode 100644
index 0000000..a49d54d
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/dag_swimlane_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/44e5579e/tez-ui/app/scripts/controllers/dag_tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_tasks.js b/tez-ui/app/scripts/controllers/dag_tasks.js
new file mode 100644
index 0000000..ef4cc7a
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/dag_tasks.js
@@ -0,0 +1,111 @@
+/**
+ * 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.DagTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+	reloadData: function() {
+		this.loadEntities();
+	}.observes('id'),
+
+	// required by the PaginatedContentMixin
+	parentEntityType: 'dag',
+	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}}")
+      }),
+      //filterID: 'task_id',
+      contentPath: 'id',
+    });
+
+    var vertexCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
+      textAlign: 'text-align-left',
+      headerCellName: 'Vertex ID',
+      filterID: 'vertex_id',
+      contentPath: 'vertexID'
+    });
+
+    var startTimeCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Start 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 actionsCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Actions',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          '<span class="ember-table-content">\
+          {{#link-to "task.counters" view.cellContent}}counters{{/link-to}}&nbsp;\
+          {{#link-to "task.attempts" view.cellContent}}attempts{{/link-to}}\
+          </span>'
+          )
+      }),
+      contentPath: 'id'
+    });
+
+		return [idCol, vertexCol, startTimeCol, endTimeCol, statusCol, actionsCol];
+	}.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/dag_vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dag_vertices.js b/tez-ui/app/scripts/controllers/dag_vertices.js
new file mode 100644
index 0000000..0000fcd
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/dag_vertices.js
@@ -0,0 +1,103 @@
+/**
+ * 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.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+	reloadData: function() {
+		this.loadEntities();
+	}.observes('id'),
+
+	// required by the PaginatedContentMixin
+	parentEntityType: 'dag',
+	childEntityType: 'vertex',
+
+	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: 'Vertex ID',
+      tableCellViewClass: Em.Table.TableCell.extend({
+      	template: Em.Handlebars.compile(
+      		"{{#link-to 'vertex' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+      }),
+      //filterID: 'task_id',
+      contentPath: 'id',
+    });
+
+    var nameCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Name',
+      contentPath: 'name',
+    });
+
+    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 numTasksCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Tasks',
+      contentPath: 'numTasks'
+    });
+
+    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)
+        };
+      }
+    });
+
+		return [idCol, nameCol, startTimeCol, endTimeCol, numTasksCol, statusCol];
+	}.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/dags_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/dags_controller.js b/tez-ui/app/scripts/controllers/dags_controller.js
index e92f281..a4ec126 100644
--- a/tez-ui/app/scripts/controllers/dags_controller.js
+++ b/tez-ui/app/scripts/controllers/dags_controller.js
@@ -149,7 +149,7 @@ App.DagsController = Em.ArrayController.extend({
       });
     }
 
-    var idColumn = Em.Table.ColumnDefinition.create({
+    var idCol = Em.Table.ColumnDefinition.create({
       textAlign: 'text-align-left',
       headerCellName: 'Dag Id',
       tableCellViewClass: Em.Table.TableCell.extend({
@@ -160,9 +160,9 @@ App.DagsController = Em.ArrayController.extend({
       	return row.get('id');
       }
     });
-    var nameColumn = columnHelper('Name', 'name');
-    var userColumn = columnHelper('Submitter', 'user');
-    var statusColumn = Em.Table.ColumnDefinition.create({
+    var nameCol = columnHelper('Name', 'name');
+    var userCol = columnHelper('Submitter', 'user');
+    var statusCol = Em.Table.ColumnDefinition.create({
       textAlign: 'text-align-left',
       headerCellName: 'Status',
       tableCellViewClass: Em.Table.TableCell.extend({
@@ -178,22 +178,29 @@ App.DagsController = Em.ArrayController.extend({
         };
       }
     });
-    var startTimeColumn = Em.Table.ColumnDefinition.create({
+    var submittedTimeCol = Em.Table.ColumnDefinition.create({
       textAlign: 'text-align-left',
-      headerCellName: 'Submission Time',
+      headerCellName: 'Submitted Time',
+      getCellContent: function(row) {
+        return App.Helpers.date.dateFormat(row.get('submittedTime'));
+      }
+    });
+    var startTimeCol = Em.Table.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Start Time',
       getCellContent: function(row) {
       	return App.Helpers.date.dateFormat(row.get('startTime'));
       }
     });
-    var appIdColumn = columnHelper('Application ID', 'applicationId');
-    var endTimeColumn = Em.Table.ColumnDefinition.create({
+    var appIdCol = columnHelper('Application ID', 'applicationId');
+    var endTimeCol = Em.Table.ColumnDefinition.create({
       textAlign: 'text-align-left',
       headerCellName: 'End Time',
       getCellContent: function(row) {
         return App.Helpers.date.dateFormat(row.get('endTime'));
       }
     });
-    return [idColumn, nameColumn, userColumn, statusColumn, startTimeColumn, appIdColumn];
+    return [idCol, nameCol, userCol, statusCol, submittedTimeCol, startTimeCol, appIdCol];
   }.property(),
 
 

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/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
deleted file mode 100644
index a49d54d..0000000
--- a/tez-ui/app/scripts/controllers/task_attempts_controller.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/**
- * 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/44e5579e/tez-ui/app/scripts/controllers/task_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/task_controller.js b/tez-ui/app/scripts/controllers/task_controller.js
index ad3e455..f4e8358 100644
--- a/tez-ui/app/scripts/controllers/task_controller.js
+++ b/tez-ui/app/scripts/controllers/task_controller.js
@@ -33,6 +33,7 @@ App.TaskController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
 
 	childDisplayViews: [
 		Ember.Object.create({title: 'Details', linkTo: 'task.index'}),
+		Ember.Object.create({title: 'Task Attempts', linkTo: 'task.attempts'}),
 		Ember.Object.create({title: 'Counters', linkTo: 'task.counters'}),
 	],
 

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/task_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/task_index_controller.js b/tez-ui/app/scripts/controllers/task_index_controller.js
index 2cff0d5..fa36314 100644
--- a/tez-ui/app/scripts/controllers/task_index_controller.js
+++ b/tez-ui/app/scripts/controllers/task_index_controller.js
@@ -16,8 +16,6 @@
  * limitations under the License.
  */
 
- require('scripts/controllers/show_tasks_view_controller');
-
  //TODO: watch individual counters.
 App.TaskIndexController = Em.ObjectController.extend({
 	controllerName: 'TaskIndexController',
@@ -26,5 +24,4 @@ App.TaskIndexController = Em.ObjectController.extend({
 		return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
 	}.property('id', 'status', 'counterGroups'),
 
-	showTasksViewController: App.ShowTasksViewController.create()
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/controllers/task_task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/task_task_attempts_controller.js b/tez-ui/app/scripts/controllers/task_task_attempts_controller.js
new file mode 100644
index 0000000..2e2ef30
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/task_task_attempts_controller.js
@@ -0,0 +1,123 @@
+/**
+ * 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.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+	reloadData: function() {
+		this.loadEntities();
+	}.observes('id'),
+
+	// required by the PaginatedContentMixin
+	parentEntityType: 'task',
+	childEntityType: 'task_attempt',
+
+	filterValues: {},
+
+/*
+  reloadWhenFiltersChange: function() {
+    var filters = {
+      id: null,
+      primary: {},
+      secondary: {}
+    };
+    var fv = this.filterValues;
+    filters.primary.TEZ_TAS = 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 'taskAttempt' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+      }),
+      //filterID: 'task_id',
+      contentPath: 'id',
+    });
+
+		/*
+    var vertexCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
+      textAlign: 'text-align-left',
+      headerCellName: 'Vertex ID',
+      filterID: 'vertex_id',
+      contentPath: 'vertexID'
+    });
+*/
+
+    var startTimeCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Start 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 nodeIdCol = App.ExTable.ColumnDefinition.create({
+      textAlign: 'text-align-left',
+      headerCellName: 'Node ID',
+      contentPath: 'nodeId'
+    });
+
+    var containerCol = App.ExTable.ColumnDefinition.create({
+    	textAlign: 'text-align-left',
+      headerCellName: 'Container ID',
+      contentPath: 'containerId'
+    });
+
+		return [idCol, startTimeCol, endTimeCol, statusCol, nodeIdCol, containerCol];
+	}.property(),
+});
+
+
+App.TaskAttemptIndexController = Em.ObjectController.extend({
+  controllerName: 'TaskAttemptIndexController',
+
+  taskIconStatus: 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/44e5579e/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
deleted file mode 100644
index 6e8877e..0000000
--- a/tez-ui/app/scripts/mappers/task_attempt_mapper.js
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- * 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/44e5579e/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
new file mode 100644
index 0000000..7288759
--- /dev/null
+++ b/tez-ui/app/scripts/mixins/paginated_content.js
@@ -0,0 +1,175 @@
+/**
+ * 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 modelToATSType = {
+	dag: 'TEZ_DAG_ID',
+	task: 'TEZ_TASK_ID',
+	taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
+};
+
+var childEntityTypeForParent = {
+	dag: 'task',
+	task: 'taskAttempt'
+}
+
+App.PaginatedContentMixin = Em.Mixin.create({
+	count: 5,
+	
+	fromID: '',
+
+	/* There is currently no efficient way in ATS to get pagination data, so we fake one.
+   * store the first dag id on a page so that we can navigate back and store the last one 
+   * (not shown on page to get the id where next page starts)
+   */
+  navIDs: {
+    prevIDs: [],
+    currentID: undefined,
+    nextID: undefined
+  },
+
+  entities: [],
+  _paginationFilters: {},
+	loading: true,
+
+  getChildEntityType: function(parentType) {
+    return childEntityTypeForParent[parentType];
+  },
+
+  sortedContent: function() {
+    var sorted = Em.ArrayController.create({
+      model: this.get('entities'),
+      sortProperties: ['startTime'],
+      sortAscending: false
+    });
+    this.updatePagination(sorted.toArray());
+    return sorted.slice(0, this.count);
+  }.property('entities', 'numEntities'),
+
+	loadEntities: function() {
+		var that = this;
+		var parentEntityType = this.get('parentEntityType');
+		var childEntityType = this.get('childEntityType');
+		this.get('store').unloadAll(childEntityType);
+		this.get('store').findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
+			that.set('entities', entities);
+			that.set('loading', false);
+		}).catch(function(jqXHR){
+			alert('failed');
+		});
+	},
+
+	setFiltersAndLoadEntities: function(filters) {
+		this._paginationFilters = filters;
+		this.resetNavigation();
+		this.loadEntities();
+	},
+
+	resetNavigation: function() {
+		this.set('navIDs.prevIDs', []);
+		this.set('navIDs.currentID', '');
+		this.set('navIDs.nextID', '');
+		this.set('fromID', '');
+	},
+
+	updatePagination: function(dataArray) {
+    if (!!dataArray && dataArray.get('length') > 0) {
+      this.set('navIDs.currentID', dataArray.objectAt(0).get('id'));
+      var nextID = undefined;
+      if (dataArray.get('length') > this.count) {
+        // save the last id, so that we can use that as firt id on next page.
+        nextID = dataArray.objectAt(this.count).get('id');
+      }
+      this.set('navIDs.nextID', nextID);
+    }
+  },
+
+  hasPrev: function() {
+    return this.navIDs.prevIDs.length > 0;
+  }.property('navIDs.prevIDs.[]', 'navIDs.prevIDs.length', 'fromID'),
+
+  hasNext: function() {
+    return !!this.navIDs.nextID;
+  }.property('navIDs.nextID'),
+
+  actions:{
+    // go to previous page
+    navigatePrev: function () {
+      var prevPageId = this.navIDs.prevIDs.popObject();
+      this.set('fromID', prevPageId);
+      this.set('loading', true);
+      this.loadEntities();
+    },
+
+    // goto first page.
+    navigateFirst: function() {
+      var firstPageId = this.navIDs.prevIDs[0];
+      this.set('navIDs.prevIDs', []);
+      this.set('fromID', firstPageId);
+      this.set('loading', true);
+      this.loadEntities();
+    },
+
+    // go to next page
+    navigateNext: function () {
+      this.navIDs.prevIDs.pushObject(this.navIDs.currentID);
+      this.set('fromID', this.get('navIDs.nextID'));
+      this.set('loading', true);
+      this.loadEntities();
+    },
+  },
+
+  _concatFilters: function(obj) {
+  	var p = [];
+		for(var k in obj) {
+			if (!Em.empty(obj[k])) {
+				p.push(k + ':' + obj[k]);
+			}
+		}
+		return p.join(',');
+  },
+
+	getFilterProperties: function() {
+		var params = {
+			limit: this.count + 1
+		};
+
+		var f = this._paginationFilters;
+		var primary = f.primary;
+		var secondary = f.secondary || {};
+
+		primary = this._concatFilters(primary);
+		if (Em.empty(primary)) {
+			primary = modelToATSType[this.get('parentEntityType')] + ':' + this.get('id');
+		}
+
+		secondary = this._concatFilters(secondary);
+
+		if (!Em.empty(primary)) {
+			params['primaryFilter'] = primary;
+		}
+
+		if (!Em.empty(secondary)) {
+			params['secondaryFilter'] = secondary;
+		}
+
+		if (!Em.empty(this.fromID)) {
+			params['fromId'] = this.fromID;
+		}
+
+		return params;
+	},
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/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 5133286..43353ba 100644
--- a/tez-ui/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/app/scripts/models/TimelineRestAdapter.js
@@ -93,6 +93,7 @@ App.TimelineSerializer = DS.RESTSerializer.extend({
 
 var timelineJsonToDagMap = {
   id: 'entity',
+  submittedTime: 'starttime',
   startTime: 'otherinfo.startTime',
   endTime: 'otherinfo.endTime',
   name: 'primaryfilters.dagName.0',
@@ -147,6 +148,8 @@ App.DagSerializer = App.TimelineSerializer.extend({
   },
 });
 
+var containerIdRegex = /.*(container_.*?)\/.*/;
+var nodeIdRegex = /([^\/]*)\//;
 var timelineJsonToTaskAttemptMap = {
   id: 'entity',
   startTime: 'otherinfo.startTime',
@@ -158,10 +161,16 @@ var timelineJsonToTaskAttemptMap = {
   dagID: 'primaryfilters.TEZ_DAG_ID.0',
   containerId: { custom: function (source) {
     var inProgressLogsURL = Em.get(source, 'otherinfo.inProgressLogsURL');
-    var regex = /.*(container_.*?)\/.*/;
-    var match = regex.exec(inProgressLogsURL);
+    var match = containerIdRegex.exec(inProgressLogsURL);
     return match[1];
-  }}
+  }},
+  nodeId: {
+    custom: function(source) {
+      var inProgressLogsURL = Em.get(source, 'otherinfo.inProgressLogsURL');
+      var match = nodeIdRegex.exec(inProgressLogsURL);
+      return match[1];
+    }
+  }
 };
 
 
@@ -216,6 +225,7 @@ var timelineJsonToTaskMap = {
   counterGroups: 'counterGroups',
   vertexID: 'primaryfilters.TEZ_VERTEX_ID.0',
   dagID: 'primaryfilters.TEZ_DAG_ID.0',
+  numAttempts: 'relatedentities'
 };
 
 App.TaskSerializer = App.TimelineSerializer.extend({
@@ -260,3 +270,58 @@ App.TaskSerializer = App.TimelineSerializer.extend({
     return Em.JsonMapper.map(hash, timelineJsonToTaskMap);
   },
 });
+
+var timelineJsonToVertexMap = {
+  id: 'entity',
+  name: 'otherinfo.vertexName',
+  dagID: 'primaryfilters.TEZ_DAG_ID.0',
+  startTime: 'otherinfo.startTime',
+  endTime: 'otherinfo.endTime',
+  status: 'otherinfo.status',
+  diagnostics: 'otherinfo.diagnostics',
+  counterGroups: 'counterGroups',
+  numTasks: 'otherinfo.numTasks'
+};
+
+App.VertexSerializer = App.TimelineSerializer.extend({
+  _normalizeSingleVertexPayload: function(vertex) {
+    var normalizedCounterGroupData = this.normalizeCounterGroupsHelper('vertex', vertex.entity, 
+      vertex);
+    vertex.counterGroups = normalizedCounterGroupData.counterGroupsIDs;
+
+    delete vertex.otherinfo.counters;
+
+    return {
+      vertex: vertex,
+      counterGroups: normalizedCounterGroupData.counterGroups,
+      counters: normalizedCounterGroupData.counters
+    };
+  },
+
+  normalizePayload: function(rawPayload) {
+    if (!!rawPayload.vertices) {
+      var normalizedPayload = {
+        vertices: [],
+        counterGroups: [],
+        counters: []
+      };
+      rawPayload.vertices.forEach(function(vertex){
+        var n = this._normalizeSingleVertexPayload(vertex);
+        normalizedPayload.vertices.push(n.vertex);
+        [].push.apply(normalizedPayload.counterGroups, n.counterGroups);
+        [].push.apply(normalizedPayload.counters, n.counters);
+      }, this);
+      
+      // delete so that we dont hang on to the json data.
+      delete rawPayload.vertex;
+
+      return normalizedPayload;
+    } else {
+      return this._normalizeSingleVertexPayload(rawPayload.vertex);
+    }
+  },
+
+  normalize: function(type, hash, prop) {
+    return Em.JsonMapper.map(hash, timelineJsonToVertexMap);
+  },
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/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 df4a5c4..3fc9c83 100644
--- a/tez-ui/app/scripts/models/dag.js
+++ b/tez-ui/app/scripts/models/dag.js
@@ -17,6 +17,8 @@
 
 App.Dag = App.AbstractEntity.extend({
 
+  submittedTime: DS.attr('number'),
+  
   // start time of the entity
   startTime: DS.attr('number'),
 
@@ -41,9 +43,9 @@ App.Dag = App.AbstractEntity.extend({
 	// diagnostics info if any.
 	diagnostics: DS.attr('string'),
 
-	//vertices: DS.hasMany('dagVertex'),
+	//vertices: DS.hasMany('vertex'),
 
-	//edges: DS.hasMany('dagEdge'),
+	//edges: DS.hasMany('edge'),
 
   counterGroups: DS.hasMany('counterGroup', { inverse: 'parent' })
 });
@@ -68,34 +70,34 @@ App.Counter = DS.Model.extend({
   parent: DS.belongsTo('counterGroup')
 });
 
-App.DagEdge = DS.Model.extend({
+App.Edge = DS.Model.extend({
 
-  fromVertex: DS.belongsTo('dagVertex'),
+  fromVertex: DS.belongsTo('vertex'),
 
-  toVertex: DS.belongsTo('dagVertex'),
+  toVertex: DS.belongsTo('vertex'),
 
   /**
    * Type of this edge connecting vertices. Should be one of constants defined
-   * in 'App.DagEdgeType'.
+   * in 'App.EdgeType'.
    */
   edgeType: DS.attr('string'),
 
   dag: DS.belongsTo('dag')
 });
 
-App.DagVertex = DS.Model.extend({
+App.Vertex = DS.Model.extend({
   name: DS.attr('string'),
 
   dag: DS.belongsTo('dag'),
 
   /**
    * State of this vertex. Should be one of constants defined in
-   * App.DagVertexState.
+   * App.VertexState.
    */
-  state: DS.attr('string'),
+  status: DS.attr('string'),
 
   /**
-   * Vertex type has to be one of the types defined in 'App.DagVertexType'
+   * Vertex type has to be one of the types defined in 'App.VertexType'
    * @return {string}
    */
   type: DS.attr('string'),
@@ -103,12 +105,12 @@ App.DagVertex = DS.Model.extend({
   /**
    * A vertex can have multiple incoming edges.
    */
-  incomingEdges: DS.hasMany('dagEdge'),
+  incomingEdges: DS.hasMany('edge', {inverse: 'fromVertex' }),
 
   /**
    * This vertex can have multiple outgoing edges.
    */
-  outgoingEdges: DS.hasMany('dagEdge'),
+  outgoingEdges: DS.hasMany('edge', {inverse: 'toVertex'}),
 
   startTime: DS.attr('number'),
 
@@ -142,7 +144,7 @@ App.DagVertex = DS.Model.extend({
   /**
    * Number of actual Map/Reduce tasks in this vertex
    */
-  tasksCount: DS.attr('number'),
+  numTasks: DS.attr('number'),
 
   tasksNumber: function () {
     return this.getWithDefault('tasksCount', 0);
@@ -216,10 +218,12 @@ App.Task = App.AbstractEntity.extend({
 
   diagnostics: DS.attr('string'),
 
+  numAttempts: DS.attr('number'),
+
   counterGroups: DS.hasMany('counterGroup', { inverse: 'parent' })
 });
 
-App.DagVertexState = {
+App.VertexState = {
   NEW: "NEW",
   INITIALIZING: "INITIALIZING",
   INITED: "INITED",
@@ -232,13 +236,13 @@ App.DagVertexState = {
   JOBFAILED: "JOB FAILED"
 };
 
-App.DagVertexType = {
+App.VertexType = {
   MAP: 'MAP',
   REDUCE: 'REDUCE',
   UNION: 'UNION'
 };
 
-App.DagEdgeType = {
+App.EdgeType = {
   SCATTER_GATHER: "SCATTER_GATHER",
   BROADCAST: "BROADCAST",
   CONTAINS: "CONTAINS"

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/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
index 0bc3aec..db1d3c1 100644
--- a/tez-ui/app/scripts/models/task_attempt.js
+++ b/tez-ui/app/scripts/models/task_attempt.js
@@ -30,6 +30,7 @@ App.TaskAttempt = App.AbstractEntity.extend({
 
 	// container
 	containerId: DS.attr('string'),
+  nodeId: DS.attr('string'),
 
   // status of the task attempt
 	status: DS.attr('string'),

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/router.js b/tez-ui/app/scripts/router.js
index a632b7a..3540495 100644
--- a/tez-ui/app/scripts/router.js
+++ b/tez-ui/app/scripts/router.js
@@ -19,12 +19,16 @@
 App.Router.map(function() {
 	this.resource('dags', { path: '/' });
 	this.resource('dag', { path: '/dag/:dag_id'}, function() {
+		this.route('vertices'),
+		this.route('tasks'),
 		this.route('counters'),
-		this.route('vertex'),
 		this.route('swimlane')
 	});
+	this.resource('vertex', {path: '/vertex/:vertex_id'});
+	
 	this.resource('tasks', {path: '/tasks/:dag_id'});
 	this.resource('task', {path: '/task/:task_id'}, function(){
+		this.route('attempts');
 		this.route('counters');
 	});
 	this.resource('taskAttempt', {path: '/task_attempt/:task_attempt_id'}, function() {

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/store.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/store.js b/tez-ui/app/scripts/store.js
deleted file mode 100644
index 21cae3e..0000000
--- a/tez-ui/app/scripts/store.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/**
- * 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.Store = DS.Store.extend();
-//App.ApplicationAdapter = DS.FixtureAdapter.extend();
-//App.ApplicationAdapter = App.TimelineRestAdapter.extend();

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/views/show_tasks_view.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/views/show_tasks_view.js b/tez-ui/app/scripts/views/show_tasks_view.js
deleted file mode 100644
index 1c196e5..0000000
--- a/tez-ui/app/scripts/views/show_tasks_view.js
+++ /dev/null
@@ -1,81 +0,0 @@
-App.ShowTasksView = Em.View.extend({
-	templateName: 'views/show_tasks',
-
-	parentEntityType: '',
-	parentEntityID: '',
-
-	init: function() {
-		this.controller.set('store', this.store);
-		this.controller.set('content', this);
-	},
-
-	columns: function() {
-    var columnHelper = function(columnName, valName) {
-      return Em.Table.ColumnDefinition.create({
-        textAlign: 'text-align-left',
-        headerCellName: columnName,
-        getCellContent: function(row) {
-          return row.get(valName);
-        }
-      });
-    }
-
-    var idColumn = Em.Table.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      //TODO: change hard coding.
-      headerCellName: this.get('parentEntityType') == 'task' ? 'Task Attempt ID' : 'Task Id',
-      tableCellViewClass: Em.Table.TableCell.extend({
-      	template: Em.Handlebars.compile(
-          this.get('parentEntityType') == 'task' ?
-          "{{#link-to 'taskAttempt' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}" :
-          "{{#link-to 'task' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
-      }),
-      getCellContent: function(row) {
-      	return row.get('id');
-      }
-    });
-
-    var vertexColumn = columnHelper('Vertex', 'vertexID');
-
-    var startTimeColumn = Em.Table.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      headerCellName: 'Submission Time',
-      getCellContent: function(row) {
-      	return App.Helpers.date.dateFormat(row.get('startTime'));
-      }
-    });
-
-    var endTimeColumn = Em.Table.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      headerCellName: 'End Time',
-      getCellContent: function(row) {
-        return App.Helpers.date.dateFormat(row.get('endTime'));
-      }
-    });
-
-    var statusColumn = Em.Table.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      headerCellName: '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)
-        };
-      }
-    });
-    
-    //TODO: for now a hack change this to take columns and type to show.
-    if (this.get('parentEntityType') == 'task') {
-      return [idColumn, startTimeColumn, endTimeColumn, statusColumn];
-    } else {
-      return [idColumn, vertexColumn, startTimeColumn, endTimeColumn, statusColumn];
-    }
-  }.property(),
-
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/scripts/views/tasks_view.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/views/tasks_view.js b/tez-ui/app/scripts/views/tasks_view.js
deleted file mode 100644
index 9f1f953..0000000
--- a/tez-ui/app/scripts/views/tasks_view.js
+++ /dev/null
@@ -1,23 +0,0 @@
-App.TasksView = Em.View.extend({
-	templateName: 'views/tasks_view',
-
-	init: function() {
-	},
-	parentEntityType: '', 
-	parentEntityID: '',
-
-	tasks: [],
-
-	getTasks: function() {
-		return;
-		var store = this.get('controller').get('store');
-		store.findQuery('task', {
-			primaryFilter: 'TEZ_DAG_ID:' + this.get('parentEntityID')
-		}).then(function() {
-		});
-	}.observes('parentEntityID'),
-
-	foo: function() {
-		var x = this.get('parentEntityID');
-	}.on('didInsertElement')
-});

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/styles/main.less
----------------------------------------------------------------------
diff --git a/tez-ui/app/styles/main.less b/tez-ui/app/styles/main.less
index 570b7c5..29581d7 100644
--- a/tez-ui/app/styles/main.less
+++ b/tez-ui/app/styles/main.less
@@ -130,4 +130,26 @@ div.indent {
 
 .countertable-row {
 	margin: 0px 0px 0px 15px;
+}
+
+.inline-display {
+	display: inline;
+}
+
+.disabled-icon {
+		pointer-events: none;
+		color:lightgray;
+}
+
+.enabled-icon {
+	cursor: pointer;
+	color: black;
+}
+
+.input-dirty {
+	background-color: yellow;
+}
+
+.table-container {
+	height: 380px;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/components/extended-table/extable.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/components/extended-table/extable.hbs b/tez-ui/app/templates/components/extended-table/extable.hbs
new file mode 100644
index 0000000..482642e
--- /dev/null
+++ b/tez-ui/app/templates/components/extended-table/extable.hbs
@@ -0,0 +1,12 @@
+{{#if controller.hasHeader}}
+  {{view Ember.Table.HeaderTableContainer}}
+{{/if}}
+{{#if controller.hasFilter}}
+	{{view App.ExTable.FilterTableContainer}}
+{{/if}}
+{{view Ember.Table.BodyTableContainer}}
+{{#if controller.hasFooter}}
+  {{view Ember.Table.FooterTableContainer}}
+{{/if}}
+{{view Ember.Table.ScrollContainer}}
+{{view Ember.Table.ColumnSortableIndicator}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/components/extended-table/filter-cell.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/components/extended-table/filter-cell.hbs b/tez-ui/app/templates/components/extended-table/filter-cell.hbs
new file mode 100644
index 0000000..2524b6e
--- /dev/null
+++ b/tez-ui/app/templates/components/extended-table/filter-cell.hbs
@@ -0,0 +1,9 @@
+<div class="ember-table-content-container" style='cursor: auto;'>
+  <span class="ember-table-content" style='white-space: nowrap; cursor: auto;'>
+    {{#if view.content.isFilterable}}
+    	{{view App.ExTable.FilterField filterValueBinding='view.content.columnFilterValue' class='inline-display'}}
+    	<!--i {{bind-attr class=':fa :fa-search-plus :inline-display view.content.isPopulated:enabled-icon:disabled-icon'}} {{action 'updateFilter' view.content}}></i>
+    	<i {{bind-attr class=':fa :fa-close :inline-display view.isPopulated:enabled-icon:disabled-icon'}} {{action 'removeFilter' view.content}}></i-->
+    {{/if}}
+  </span>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/components/extended-table/filter-container.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/components/extended-table/filter-container.hbs b/tez-ui/app/templates/components/extended-table/filter-container.hbs
new file mode 100644
index 0000000..b5e73d9
--- /dev/null
+++ b/tez-ui/app/templates/components/extended-table/filter-container.hbs
@@ -0,0 +1,15 @@
+<div class="ember-table-table-fixed-wrapper">
+  {{#if controller.numFixedColumns}}
+    {{view App.ExTable.FilterBlock classNames="ember-table-left-table-block"
+      columnsBinding="controller.fixedColumns"
+      widthBinding="controller._fixedBlockWidth"
+      heightBinding="controller.filterHeight"
+    }}
+  {{/if}}
+  {{view App.ExTable.FilterBlock classNames="ember-table-right-table-block"
+    columnsBinding="controller.tableColumns"
+    scrollLeftBinding="controller._tableScrollLeft"
+    widthBinding="controller._tableBlockWidth"
+    heightBinding="controller.filterHeight"
+  }}
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/components/extended-table/filter-row.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/components/extended-table/filter-row.hbs b/tez-ui/app/templates/components/extended-table/filter-row.hbs
new file mode 100644
index 0000000..453b76e
--- /dev/null
+++ b/tez-ui/app/templates/components/extended-table/filter-row.hbs
@@ -0,0 +1,5 @@
+{{view Ember.MultiItemViewCollectionView
+  contentBinding="view.content"
+  itemViewClassField="filterCellViewClass"
+  widthBinding="controller._tableColumnsWidth"
+}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/dag.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag.hbs b/tez-ui/app/templates/dag.hbs
index cd71631..3908f2f 100644
--- a/tez-ui/app/templates/dag.hbs
+++ b/tez-ui/app/templates/dag.hbs
@@ -1,13 +1,5 @@
 {{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 margin-small'>
 		<div class='align-left'>
 

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/dag/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag/index.hbs b/tez-ui/app/templates/dag/index.hbs
index 2fe37fc..e48e58d 100644
--- a/tez-ui/app/templates/dag/index.hbs
+++ b/tez-ui/app/templates/dag/index.hbs
@@ -79,5 +79,3 @@
     {{formatDiagnostics diagnostics}}
 	{{/bs-panel}}
 {{/if}}
-
-{{view App.ShowTasksView parentEntityType='dag' store=store parentEntityID=content.id controllerBinding='showTasksViewController'}}

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/dag/tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag/tasks.hbs b/tez-ui/app/templates/dag/tasks.hbs
new file mode 100644
index 0000000..a342ae1
--- /dev/null
+++ b/tez-ui/app/templates/dag/tasks.hbs
@@ -0,0 +1,29 @@
+{{#unless loading}}
+	<div class='margin-small'>
+		<span class='align-right'>
+			{{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}}
+	{{!todo remove unnecessary stuff}}

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/dag/vertex.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag/vertex.hbs b/tez-ui/app/templates/dag/vertex.hbs
deleted file mode 100644
index decadbc..0000000
--- a/tez-ui/app/templates/dag/vertex.hbs
+++ /dev/null
@@ -1 +0,0 @@
-PlaceHolder for tasks
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/dag/vertices.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dag/vertices.hbs b/tez-ui/app/templates/dag/vertices.hbs
new file mode 100644
index 0000000..6bacc38
--- /dev/null
+++ b/tez-ui/app/templates/dag/vertices.hbs
@@ -0,0 +1,28 @@
+{{#unless loading}}
+	<div class='margin-small'>
+		<span class='align-right'>
+			{{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

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/task/attempts.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/task/attempts.hbs b/tez-ui/app/templates/task/attempts.hbs
new file mode 100644
index 0000000..6bacc38
--- /dev/null
+++ b/tez-ui/app/templates/task/attempts.hbs
@@ -0,0 +1,28 @@
+{{#unless loading}}
+	<div class='margin-small'>
+		<span class='align-right'>
+			{{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

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/task/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/task/index.hbs b/tez-ui/app/templates/task/index.hbs
index 33da8fd..eda26f0 100644
--- a/tez-ui/app/templates/task/index.hbs
+++ b/tez-ui/app/templates/task/index.hbs
@@ -55,5 +55,3 @@
     {{formatDiagnostics diagnostics}}
 	{{/bs-panel}}
 {{/if}}
-
-{{view App.ShowTasksView parentEntityType='task' store=store parentEntityID=content.id controllerBinding='showTasksViewController'}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/44e5579e/tez-ui/app/templates/taskAttempt/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/taskAttempt/index.hbs b/tez-ui/app/templates/taskAttempt/index.hbs
new file mode 100644
index 0000000..db17b2e
--- /dev/null
+++ b/tez-ui/app/templates/taskAttempt/index.hbs
@@ -0,0 +1,43 @@
+<div class='type-table fill-full margin-small-horizontal'>
+	<div class='align-left'>
+		<table class='detail-list'>
+			<tbody>
+				<tr>
+					<td>{{t common.status}}</td>
+					<td>
+						{{status}}
+						<i {{bind-attr class=':task-status taskIconStatus'}}></i>
+					</td>
+				</tr>
+				<tr>
+					<td>Container</td>
+					<td>{{containerId}}</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/44e5579e/tez-ui/app/templates/views/show_tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/views/show_tasks.hbs b/tez-ui/app/templates/views/show_tasks.hbs
deleted file mode 100644
index 6e9017f..0000000
--- a/tez-ui/app/templates/views/show_tasks.hbs
+++ /dev/null
@@ -1,38 +0,0 @@
-{{#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'>
-	  {{table-component
-	    hasFooter=false
-	    columnsBinding='columns'
-	    contentBinding='sortedContent'
-	    forceFillColumns=true
-	  }}
-	</div>
-
-	<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>
-{{else}}
-	{{partial 'utils/loadingSpinner'}}	
-{{/unless}}
\ No newline at end of file


Mime
View raw message