tez-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From hit...@apache.org
Subject git commit: TEZ-1720. Allow filters in all tables and also to pass in filters using url params. (Prakash Ramachandran via hitesh)
Date Wed, 29 Oct 2014 23:02:29 GMT
Repository: tez
Updated Branches:
  refs/heads/TEZ-8 ce6d17a91 -> c327ac6f3


TEZ-1720. Allow filters in all tables and also to pass in filters using url params. (Prakash Ramachandran via hitesh)


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

Branch: refs/heads/TEZ-8
Commit: c327ac6f3bfbf3dfbfdd3dfda664940cb891124f
Parents: ce6d17a
Author: Hitesh Shah <hitesh@apache.org>
Authored: Wed Oct 29 16:01:49 2014 -0700
Committer: Hitesh Shah <hitesh@apache.org>
Committed: Wed Oct 29 16:01:49 2014 -0700

----------------------------------------------------------------------
 CHANGES.txt                                     |   2 +-
 tez-ui/app/scripts/components/extended-table.js |  85 +++------
 .../scripts/controllers/dag_index_controller.js |   4 +
 tez-ui/app/scripts/controllers/dag_tasks.js     |  70 ++++---
 tez-ui/app/scripts/controllers/dag_vertices.js  |  88 +++++----
 .../app/scripts/controllers/dags_controller.js  | 183 +++++++------------
 .../controllers/show_tasks_view_controller.js   | 135 --------------
 .../task_task_attempts_controller.js            |  64 +++----
 .../app/scripts/controllers/tasks_controller.js |  55 ++----
 .../scripts/controllers/vertex_controller.js    |   4 +-
 .../controllers/vertex_index_controller.js      |   8 +
 .../controllers/vertex_tasks_controller.js      |  59 +++---
 tez-ui/app/scripts/helpers/date.js              |   2 +
 tez-ui/app/scripts/helpers/misc.js              |  51 ++++--
 tez-ui/app/scripts/mixins/paginated_content.js  |  23 +--
 tez-ui/app/scripts/router.js                    | 147 ++++++++++-----
 tez-ui/app/styles/main.less                     |  25 ++-
 .../components/extended-table/filter-cell.hbs   |   2 -
 tez-ui/app/templates/dag/index.hbs              |  29 +--
 tez-ui/app/templates/dag/tasks.hbs              |   3 +-
 tez-ui/app/templates/dag/vertices.hbs           |   2 +-
 tez-ui/app/templates/dags.hbs                   |  65 ++++---
 tez-ui/app/templates/task/attempts.hbs          |   2 +-
 tez-ui/app/templates/vertex.hbs                 |   7 -
 tez-ui/app/templates/vertex/index.hbs           |   5 +
 tez-ui/app/templates/vertex/tasks.hbs           |   2 +-
 26 files changed, 489 insertions(+), 633 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index fcbadcf..e3dec9d 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -10,7 +10,7 @@ ALL CHANGES:
   TEZ-1615. Skeleton framework for Tez UI
   TEZ-1604. Task View for Tez UI
   TEZ-1603. Vertex View for Tez UI.
-
+  TEZ-1720. Allow filters in all tables and also to pass in filters using url params.
 
 Release 0.5.2: Unreleased
 

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 48d11bf..5047af9 100644
--- a/tez-ui/app/scripts/components/extended-table.js
+++ b/tez-ui/app/scripts/components/extended-table.js
@@ -16,9 +16,7 @@
  * limitations under the License.
  */
 
- App.ExTable = Ember.Namespace.create();
-
-//TODO: fix top calculation in FooterTableContainer
+App.ExTable = Ember.Namespace.create();
 
 App.ExTable.FilterField = Em.TextField.extend({
 	classNames: ['filter'],
@@ -31,20 +29,16 @@ App.ExTable.FilterField = Em.TextField.extend({
   	return !Em.isEmpty(this.get('value'));
   }.property('value'),
   insertNewline: function(event) {
-  	if (this.get('isInputDirty')) {
-  		this.set('filterValue', this.get('value'))
-  	}
+    if (this.get('isInputDirty')) {
+      this.set('filterValue', this.get('value'));
+      this.get('parentView.controller').send('filterUpdated', 
+        this.get('parentView.content'), this.get('value'));
+    }
   },
   cancel: function() {
-  	//TODO: ignoring cancel for now. user needs to press enter.
-  	//this.set('filterValue', this.get('value'))
+    // cancel is ignored. user needs to press enter. This is done in order to avoid 
+    // two requests when user wants to clear the current input and enter new 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')
@@ -91,23 +85,22 @@ App.ExTable.FilterCell = Ember.View.extend(Ember.AddeparMixins.StyleBindingsMixi
   height: function() {
   	return this.get('controller._filterHeight');
   }.property('controller._filterHeight'),
-  isPopulated: function() {//TODO: remove
-  	return true;
-  }.property()
-  //TODO: handle resizing if required.
+  // Currently resizing is not handled automatically. if required will need to do here.
 });
 
 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',
+  init: function() {
+    if (!!this.filterID) {
+      var columnFilterValueBinding = Em.Binding
+        .oneWay('controller._parentView.context.' + this.filterID)
+        .to('columnFilterValue');
+      columnFilterValueBinding.connect(this);
+    }
+  },
+  textAlign: 'text-align-left',
+  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({
@@ -117,37 +110,15 @@ App.ExTable.TableComponent = Ember.Table.EmberTableComponent.extend({
 	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);
-			}
-		}
-	},
+  actions: {
+    filterUpdated: function(columnDef, value) {
+      var filterID = columnDef.get('filterID');
+      filterID = filterID || columnDef.get('headerCellName').underscore();
+      if (this.get('onFilterUpdated')) {
+      	this.sendAction('onFilterUpdated', filterID, value);
+      }
+    }
+  },
 
 	// private variables
 	// Dynamic filter height that adjusts according to the filter content height

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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 6837c57..14a54ea 100644
--- a/tez-ui/app/scripts/controllers/dag_index_controller.js
+++ b/tez-ui/app/scripts/controllers/dag_index_controller.js
@@ -48,6 +48,10 @@ App.DagIndexController = Em.ObjectController.extend({
 		return this.get('failedTasks') > 0;
 	}.property('id', 'counterGroups'),
 
+  failedTasksLink: function() {
+    return '/#tasks?status=FAILED&parentType=TEZ_DAG_ID&parentID=' + this.get('id');
+  }.property(),
+
 	actions: {
 		showFailedTasks: function() {
 			alert('not implemented');

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index ef4cc7a..43e6809 100644
--- a/tez-ui/app/scripts/controllers/dag_tasks.js
+++ b/tez-ui/app/scripts/controllers/dag_tasks.js
@@ -17,67 +17,80 @@
  */
 
 App.DagTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
-	reloadData: function() {
-		this.loadEntities();
-	}.observes('id'),
+  needs: "dag",
 
-	// required by the PaginatedContentMixin
-	parentEntityType: 'dag',
-	childEntityType: 'task',
+  // required by the PaginatedContentMixin
+  childEntityType: 'task',
 
-	filterValues: {},
+  queryParams: {
+    status_filter: 'status',
+    vertex_id_filter: 'vertex_id',
+  },
+  status_filter: null,
+  vertex_id_filter: null,
 
-  reloadWhenFiltersChange: function() {
+  loadData: function() {
     var filters = {
-      id: null,
-      primary: {},
-      secondary: {}
-    };
-    var fv = this.filterValues;
-    filters.primary.TEZ_VERTEX_ID = fv.vertex_id;
-    filters.secondary.status = fv.status;
+      primary: {
+        TEZ_DAG_ID: this.get('controllers.dag.id'),
+        TEZ_VERTEX_ID: this.vertex_id_filter,
+      },
+      secondary: {
+        status: this.status_filter
+      }
+    }
     this.setFiltersAndLoadEntities(filters);
-  }.observes('filterValues.task_id', 'filterValues.vertex_id', 'filterValues.status'),
+  },
+
+  actions : {
+    filterUpdated: function(filterID, value) {
+      // any validations required goes here.
+      if (!!value) {
+        this.set(filterID, value);
+      } else {
+        this.set(filterID, null);
+      }
+      this.loadData();
+    }
+  },
 
 	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',
+      filterID: 'vertex_id_filter',
       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',
+    var runTimeCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Run Time',
       getCellContent: function(row) {
-        return App.Helpers.date.dateFormat(row.get('endTime'));
+        var st = row.get('startTime');
+        var et = row.get('endTime');
+        if (st && et) {
+          return App.Helpers.date.durationSummary(st, et);
+        }
       }
     });
 
     var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
-      textAlign: 'text-align-left',
       headerCellName: 'Status',
-      filterID: 'status',
+      filterID: 'status_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
           '<span class="ember-table-content">&nbsp;\
@@ -93,7 +106,6 @@ App.DagTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
     });
 
     var actionsCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
       headerCellName: 'Actions',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
@@ -106,6 +118,6 @@ App.DagTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
       contentPath: 'id'
     });
 
-		return [idCol, vertexCol, startTimeCol, endTimeCol, statusCol, actionsCol];
+		return [idCol, vertexCol, startTimeCol, runTimeCol, statusCol, actionsCol];
 	}.property(),
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 0000fcd..5751de7 100644
--- a/tez-ui/app/scripts/controllers/dag_vertices.js
+++ b/tez-ui/app/scripts/controllers/dag_vertices.js
@@ -17,73 +17,87 @@
  */
 
 App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin, {
-	reloadData: function() {
-		this.loadEntities();
-	}.observes('id'),
+  needs: "dag",
 
-	// required by the PaginatedContentMixin
-	parentEntityType: 'dag',
-	childEntityType: 'vertex',
+  // required by the PaginatedContentMixin
+  childEntityType: 'vertex',
 
-	filterValues: {},
+  queryParams: {
+    status_filter: 'status'
+  },
 
-  /*
-  reloadWhenFiltersChange: function() {
+  status_filter: null,
+
+  loadData: function() {
     var filters = {
-      id: null,
-      primary: {},
-      secondary: {}
-    };
-    var fv = this.filterValues;
-    filters.primary.TEZ_VERTEX_ID = fv.vertex_id;
-    filters.secondary.status = fv.status;
+      primary: {
+        TEZ_DAG_ID: this.get('controllers.dag.id')
+      },
+      secondary: {
+        status: this.status_filter
+      }
+    }
     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',
+  },
+
+  actions : {
+    filterUpdated: function(filterID, value) {
+      // any validations required goes here.
+      if (!!value) {
+        this.set(filterID, value);
+      } else {
+        this.set(filterID, null);
+      }
+      this.loadData();
+    }
+  },
+
+  columns: function() {
+    var idCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Vertex Name',
       tableCellViewClass: Em.Table.TableCell.extend({
       	template: Em.Handlebars.compile(
-      		"{{#link-to 'vertex' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+      		"{{#link-to 'vertex' view.cellContent.id class='ember-table-content'}}{{view.cellContent.name}}{{/link-to}}")
       }),
-      //filterID: 'task_id',
-      contentPath: 'id',
+      getCellContent: function(row) {
+        return {
+          id: row.get('id'),
+          name: row.get('name')
+        };
+      }
     });
 
     var nameCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      headerCellName: 'Name',
-      contentPath: 'name',
+      headerCellName: 'Vertex ID',
+      contentPath: 'id',
     });
 
     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',
+    var runTimeCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Run Time',
       getCellContent: function(row) {
-        return App.Helpers.date.dateFormat(row.get('endTime'));
+        var st = row.get('startTime');
+        var et = row.get('endTime');
+        if (st && et) {
+          return App.Helpers.date.durationSummary(st, et);
+        }
       }
     });
 
     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',
+      filterID: 'status_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
           '<span class="ember-table-content">&nbsp;\
@@ -98,6 +112,6 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
       }
     });
 
-		return [idCol, nameCol, startTimeCol, endTimeCol, numTasksCol, statusCol];
+		return [idCol, nameCol, startTimeCol, runTimeCol, numTasksCol, statusCol];
 	}.property(),
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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 a4ec126..896db7f 100644
--- a/tez-ui/app/scripts/controllers/dags_controller.js
+++ b/tez-ui/app/scripts/controllers/dags_controller.js
@@ -16,155 +16,103 @@
  * limitations under the License.
  */
 
-App.DagsController = Em.ArrayController.extend({
+App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+  childEntityType: 'dag',
+
 	controllerName: 'DagsController',
 
 	pageTitle: 'Dags',
 
 	pageSubTitle: 'All Dags',
 
-  /* filtering and sorting related */
+  // query parameters supported through url. The same named variables in this controller get
+  // bound automatically to the ones defined in the route.
   queryParams: {
     count: true,
-    fromID: true
+    fromID: true,
+    status_filter: 'status',
+    user_filter: 'user'
   },
 
+  // paging related values. These are bound automatically to the values in url. via the queryParams
+  // defined in the route. 
   count: 10,
 
-  fromID: '',
+  fromID: null,
+
+  status_filter: null,
 
-  fromTS: '',
+  user_filter: null,
 
   fields: 'events,primaryfilters,otherinfo',
-  /* end sort & filter related */
-
-  // content is being loaded.
-  loading: true,
-
-  /* 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
-  },
 
-  updateLoading: function() {
-    this.set('loading', false);
-  }.observes('content'),
+  // The dropdown contents for number of items to show.
+  countOptions: [5, 10, 25, 50, 100],
 
-  sortedContent: function() {
-    var sorted = Em.ArrayController.create({
-      model: this.get('content'),
-      sortProperties: ['startTime'],
-      sortAscending: false
-    });
-    this.updatePagination(sorted.toArray());
-    return sorted.slice(0, this.count);
-  }.property('content.isUpdating', 'content.isLoading'),
-
-  updatePagination: function(currentPageDagIDs) {
-    if (!!currentPageDagIDs && currentPageDagIDs.length > 0) {
-      this.set('navIDs.currentID', currentPageDagIDs[0].id);
-      var nextID = undefined;
-      if (currentPageDagIDs.length > this.count) {
-        // save the last id, so that we can use that as firt id on next page.
-        nextID = currentPageDagIDs[this.count].id;
+  loadData: function() {
+    var filters = {
+      primary: {
+        user: this.user_filter
+      },
+      secondary: {
+        status: this.status_filter
       }
-      this.set('navIDs.nextID', nextID);
     }
+    this.setFiltersAndLoadEntities(filters);
   },
 
-  hasPrev: function() {
-    return this.navIDs.prevIDs.length > 0;
-  }.property('navIDs.prevIDs.[]'),
-
-  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.transitionToRoute('dags');
-    },
-
-    // goto first page.
-    navigateFirst: function() {
-      var firstPageId = this.navIDs.prevIDs[0];
-      this.set('navIDs.prevIDs', []);
-      this.set('fromID', firstPageId);
-      this.set('loading', true);
-      this.transitionToRoute('dags');
-    },
-
-    // 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.transitionToRoute('dags');
+  countUpdated: function() {
+    this.loadData();
+  }.observes('count'),
+
+  actions : {
+    filterUpdated: function(filterID, value) {
+      // any validations required goes here.
+      if (!!value) {
+        this.set(filterID, value);
+      } else {
+        this.set(filterID, null);
+      }
+      this.loadData();
     },
   },
 
-  getFilterParams: function(params) {
-    var filterParams = {
-      limit: (parseInt(params.count) || this.get('count')) + 1,
-      fields: this.get('fields')
-    };
-    var fromID = params.fromID || this.get('fromID'), 
-        fromTS = params.fromTS || this.get('fromTS'),
-        user = params.user;
-    
-    if (fromID) {
-      filterParams['fromId'] = fromID; 
-    }
-
-    if (fromTS) {
-      filterParams['fromTs'] = fromTS;
-    }
-
-    if (user) {
-      filterParams['primaryFilter'] = 'user:' + user;
-    }
-
-    return filterParams;
-  },
-
 	/* table view for dags */
   columns: function() {
     var store = this.get('store');
     var columnHelper = function(columnName, valName) {
-      return Em.Table.ColumnDefinition.create({
+      return App.ExTable.ColumnDefinition.create({
         textAlign: 'text-align-left',
         headerCellName: columnName,
-        getCellContent: function(row) {
-          return row.get(valName);
-        }
+        contentPath: valName
       });
     }
 
-    var idCol = Em.Table.ColumnDefinition.create({
+    var nameCol = App.ExTable.ColumnDefinition.create({
       textAlign: 'text-align-left',
-      headerCellName: 'Dag Id',
+      headerCellName: 'Dag Name',
       tableCellViewClass: Em.Table.TableCell.extend({
       	template: Em.Handlebars.compile(
-          "{{#link-to 'dag' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+          "{{#link-to 'dag' view.cellContent.id class='ember-table-content'}}{{view.cellContent.name}}{{/link-to}}")
       }),
       getCellContent: function(row) {
-      	return row.get('id');
+      	return {
+          id: row.get('id'),
+          name: row.get('name')
+        };
       }
     });
-    var nameCol = columnHelper('Name', 'name');
-    var userCol = columnHelper('Submitter', 'user');
-    var statusCol = Em.Table.ColumnDefinition.create({
+    var idCol = columnHelper('Dag ID', 'id');
+    var userCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin, {
+      textAlign: 'text-align-left',
+      headerCellName: 'Submitter',
+      filterID: 'user_filter',
+      contentPath: 'user'
+    }); 
+    var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
       textAlign: 'text-align-left',
       headerCellName: 'Status',
+      filterID: 'status_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
           '<span class="ember-table-content">&nbsp;\
@@ -178,29 +126,26 @@ App.DagsController = Em.ArrayController.extend({
         };
       }
     });
-    var submittedTimeCol = Em.Table.ColumnDefinition.create({
+    var submittedTimeCol = App.ExTable.ColumnDefinition.create({
       textAlign: 'text-align-left',
       headerCellName: 'Submitted Time',
       getCellContent: function(row) {
         return App.Helpers.date.dateFormat(row.get('submittedTime'));
       }
     });
-    var startTimeCol = Em.Table.ColumnDefinition.create({
+    var runTimeCol = App.ExTable.ColumnDefinition.create({
       textAlign: 'text-align-left',
-      headerCellName: 'Start Time',
+      headerCellName: 'Run Time',
       getCellContent: function(row) {
-      	return App.Helpers.date.dateFormat(row.get('startTime'));
+        var st = row.get('startTime');
+        var et = row.get('endTime');
+        if (st && et) {
+          return App.Helpers.date.durationSummary(st, et);
+        }
       }
     });
     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 [idCol, nameCol, userCol, statusCol, submittedTimeCol, startTimeCol, appIdCol];
+    return [nameCol, idCol, userCol, statusCol, submittedTimeCol, runTimeCol, appIdCol];
   }.property(),
 
 

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/scripts/controllers/show_tasks_view_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/show_tasks_view_controller.js b/tez-ui/app/scripts/controllers/show_tasks_view_controller.js
deleted file mode 100644
index d769200..0000000
--- a/tez-ui/app/scripts/controllers/show_tasks_view_controller.js
+++ /dev/null
@@ -1,135 +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 parentTypeToATSType = {
-	dag: 'TEZ_DAG_ID',
-	task: 'TEZ_TASK_ID',
-	taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
-};
-
-var childEntityTypeForParent = {
-	dag: 'task',
-	task: 'taskAttempt'
-}
-
-//TODO: This is generic view controller - name it so.
-App.ShowTasksViewController = Em.ObjectController.extend({
-	controllerName: 'ShowTasksViewController',
-
-	count: 10,
-
-  fromID: '',
-
-  fromTS: '',
-
-  /* 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: [],
-	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'),
-
-	loadEntities: function() {
-		var that = this;
-		var parentEntityType = this.get('parentEntityType');
-		var childEntityType = childEntityTypeForParent[parentEntityType];
-		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');
-		});
-	}.observes('content.parentEntityID', '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.[]'),
-
-  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);
-    },
-
-    // goto first page.
-    navigateFirst: function() {
-      var firstPageId = this.navIDs.prevIDs[0];
-      this.set('navIDs.prevIDs', []);
-      this.set('fromID', firstPageId);
-      this.set('loading', true);
-    },
-
-    // go to next page
-    navigateNext: function () {
-      this.navIDs.prevIDs.pushObject(this.navIDs.currentID);
-      this.set('fromID', this.get('navIDs.nextID'));
-      this.set('loading', true);
-    },
-  },
-
-	getFilterProperties: function() {
-		var params = {
-			primaryFilter: parentTypeToATSType[this.get('parentEntityType')] + ':' + this.get('parentEntityID'),
-			limit: this.count + 1
-		};
-
-		if (this.fromID) {
-			params['fromId'] = this.fromID;
-		}
-
-		return params;
-	},
-});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 2e2ef30..f795319 100644
--- a/tez-ui/app/scripts/controllers/task_task_attempts_controller.js
+++ b/tez-ui/app/scripts/controllers/task_task_attempts_controller.js
@@ -17,53 +17,51 @@
  */
 
 App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
-	reloadData: function() {
-		this.loadEntities();
-	}.observes('id'),
+  // required by the PaginatedContentMixin
+  childEntityType: 'task_attempt',
 
-	// required by the PaginatedContentMixin
-	parentEntityType: 'task',
-	childEntityType: 'task_attempt',
+  needs: 'task',
 
-	filterValues: {},
+  queryParams: {
+    status_filter: 'status'
+  },
+  status_filter: null,
 
-/*
-  reloadWhenFiltersChange: function() {
+  loadData: function() {
     var filters = {
-      id: null,
-      primary: {},
-      secondary: {}
-    };
-    var fv = this.filterValues;
-    filters.primary.TEZ_TAS = fv.vertex_id;
-    filters.secondary.status = fv.status;
+      primary: {
+        TEZ_TASK_ID: this.get('controllers.task.id')
+      },
+      secondary: {
+        status: this.status_filter
+      }
+    }
     this.setFiltersAndLoadEntities(filters);
-  }.observes('filterValues.task_id', 'filterValues.vertex_id', 'filterValues.status'),
-  */
+  },
+
+  actions : {
+    filterUpdated: function(filterID, value) {
+      // any validations required goes here.
+      if (!!value) {
+        this.set(filterID, value);
+      } else {
+        this.set(filterID, null);
+      }
+      this.loadData();
+    }
+  },
 
 	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'));
@@ -71,7 +69,6 @@ App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixi
     });
 
     var endTimeCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
       headerCellName: 'End Time',
       getCellContent: function(row) {
         return App.Helpers.date.dateFormat(row.get('endTime'));
@@ -79,9 +76,8 @@ App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixi
     });
 
     var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
-      textAlign: 'text-align-left',
       headerCellName: 'Status',
-      filterID: 'status',
+      filterID: 'status_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
           '<span class="ember-table-content">&nbsp;\
@@ -97,13 +93,11 @@ App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixi
     });
 
     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'
     });

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/scripts/controllers/tasks_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/tasks_controller.js b/tez-ui/app/scripts/controllers/tasks_controller.js
index 55b45a6..3573759 100644
--- a/tez-ui/app/scripts/controllers/tasks_controller.js
+++ b/tez-ui/app/scripts/controllers/tasks_controller.js
@@ -16,54 +16,35 @@
  * limitations under the License.
  */
 
-App.TasksController = Em.ArrayController.extend({
+App.TasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+  // Required by the PaginatedContentMixin
+  childEntityType: 'task',
+
 	controllerName: 'TasksController',
 
 	pageTitle: 'Tasks',
 
 	pageSubTitle: 'All Tasks',
 
-	/* There is currently no efficient way in ATS to get pagination data, so we fake one.
-   * store the first task 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
+  queryParams: {
+    parentType: true,
+    parentID: true,
+    status_filter: 'status'
   },
 
-	sortedContent: function() {
-    var sorted = Em.ArrayController.create({
-      model: this.get('content'),
-      sortProperties: ['startTime'],
-      sortAscending: false
-    });
-    this.updatePagination(sorted.toArray());
-    return sorted.slice(0, this.count);
-  }.property('content.isUpdating', 'content.isLoading'),
+  parentType: null,
+  parentID: null,
+  status_filter: null,
 
-  updatePagination: function(currentPageTaskIDs) {
-    if (!!currentPageTaskIDs && currentPageTaskIDs.length > 0) {
-      this.set('navIDs.currentID', currentPageTaskIDs[0].id);
-      var nextID = undefined;
-      if (currentPageTaskIDs.length > this.count) {
-        // save the last id, so that we can use that as firt id on next page.
-        nextID = currentPageTaskIDs[this.count].id;
+  loadData: function() {
+    var filters = {
+      primary: {},
+      secondary: {
+        status: this.status_filter
       }
-      this.set('navIDs.nextID', nextID);
     }
-  },
-
-  getFilterParams: function(params) {
-  	//TODO: other parameters.
-  	var filterParams = {};
-
-    if (params.dag_id) {
-      filterParams['primaryFilter'] = 'TEZ_DAG_ID:' + params.dag_id;
-    }
-
-    return filterParams;
+    filters.primary[this.parentType] = this.parentID;
+    this.setFiltersAndLoadEntities(filters);
   },
 
 	/* table view for tasks */

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index f5c7ef4..905d8d3 100644
--- a/tez-ui/app/scripts/controllers/vertex_controller.js
+++ b/tez-ui/app/scripts/controllers/vertex_controller.js
@@ -28,8 +28,8 @@ App.VertexController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
   }.observes('content'),
 
   pageSubTitle: function() {
-    return this.get('id');
-  }.property('id'),
+    return this.get('name');
+  }.property('name'),
 
   childDisplayViews: [
     Ember.Object.create({title: 'Details', linkTo: 'vertex.index'}),

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index c1cf234..a4252d1 100644
--- a/tez-ui/app/scripts/controllers/vertex_index_controller.js
+++ b/tez-ui/app/scripts/controllers/vertex_index_controller.js
@@ -23,4 +23,12 @@ App.VertexIndexController = Em.ObjectController.extend({
   iconStatus: function() {
     return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
   }.property('id', 'status', 'counterGroups'),
+
+  hasFailedTasks: function() {
+    return this.get('failedTasks') > 0;
+  }.property('id', 'counterGroups'),
+  
+  failedTasksLink: function() {
+    return '/#tasks?status=FAILED&parentType=TEZ_VERTEX_ID&parentID=' + this.get('id');
+  }.property(),
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 05b501c..51f3f5e 100644
--- a/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
+++ b/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
@@ -17,31 +17,42 @@
  */
 
 App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
-  reloadData: function() {
-    this.loadEntities();
-  }.observes('id'),
-
   // Required by the PaginatedContentMixin
-  parentEntityType: 'vertex',
   childEntityType: 'task',
 
-  filterValues: {},
+  needs: 'vertex',
+
+  queryParams: {
+    status_filter: 'status',
+  },
+  status_filter: null,
 
-  reloadWhenFiltersChange: function() {
+  loadData: function() {
     var filters = {
-      id: null,
-      primary: {},
-      secondary: {}
-    };
-    var fv = this.filterValues;
-    filters.primary.TEZ_VERTEX_ID = fv.vertex_id;
-    filters.secondary.status = fv.status;
+      primary: {
+        TEZ_VERTEX_ID: this.get('controllers.vertex.id')
+      },
+      secondary: {
+        status: this.status_filter
+      }
+    }
     this.setFiltersAndLoadEntities(filters);
-  }.observes('filterValues.task_id', 'filterValues.vertex_id', 'filterValues.status'),
+  },
+
+  actions : {
+    filterUpdated: function(filterID, value) {
+      // any validations required goes here.
+      if (!!value) {
+        this.set(filterID, value);
+      } else {
+        this.set(filterID, null);
+      }
+      this.loadData();
+    }
+  },
 
   columns: function() {
     var idCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
       headerCellName: 'Task ID',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
@@ -51,9 +62,7 @@ App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin
     });
 
     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(
@@ -62,7 +71,6 @@ App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin
     });
 
     var startTimeCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
       headerCellName: 'Submission Time',
       getCellContent: function(row) {
         return App.Helpers.date.dateFormat(row.get('startTime'));
@@ -70,17 +78,19 @@ App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin
     });
 
     var endTimeCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
-      headerCellName: 'End Time',
+      headerCellName: 'Run Time',
       getCellContent: function(row) {
-        return App.Helpers.date.dateFormat(row.get('endTime'));
+        var st = row.get('startTime');
+        var et = row.get('endTime');
+        if (st && et) {
+          return App.Helpers.date.durationSummary(st, et);
+        }
       }
     });
 
     var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
-      textAlign: 'text-align-left',
       headerCellName: 'Status',
-      filterID: 'status',
+      filterID: 'status_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
           '<span class="ember-table-content">&nbsp;\
@@ -96,7 +106,6 @@ App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin
     });
 
     var nodeCol = App.ExTable.ColumnDefinition.create({
-      textAlign: 'text-align-left',
       headerCellName: 'Node',
       contentPath: 'node'
     });

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/scripts/helpers/date.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/helpers/date.js b/tez-ui/app/scripts/helpers/date.js
index 9bf49ce..b9dd697 100644
--- a/tez-ui/app/scripts/helpers/date.js
+++ b/tez-ui/app/scripts/helpers/date.js
@@ -177,9 +177,11 @@ App.Helpers.date = {
     var oneDayMs = 86400000;
 
     if (lengthOfNumber < 4) {
+      time = Math.floor(time);
       return time + ' ms';
     } else if (lengthOfNumber < 7) {
       time = (time / 1000).toFixed(2);
+      time = Math.floor(time);
       return time + ' secs';
     } else if (time < oneHourMs) {
       time = (time / oneMinMs).toFixed(2);

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/scripts/helpers/misc.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/helpers/misc.js b/tez-ui/app/scripts/helpers/misc.js
index 1a5c4e8..8db04a0 100644
--- a/tez-ui/app/scripts/helpers/misc.js
+++ b/tez-ui/app/scripts/helpers/misc.js
@@ -16,23 +16,33 @@
  */
 
 App.Helpers.misc = {
-	getStatusClassForEntity: function(dag) {
-		if (dag.get('status') == 'FAILED') {
-			return 'failure';
-		}
-
-		var counterGroups = dag.get('counterGroups');
-		var numFailedTasks = this.getCounterValueForDag(counterGroups,
-				dag.get('id'), 'org.apache.tez.common.counters.DAGCounter',
-				'NUM_FAILED_TASKS'
-			); 
+  getStatusClassForEntity: function(dag) {
+    var st = dag.get('status');
+    switch(st) {
+      case 'FAILED':
+        return 'failed';
+      case 'KILLED':
+        return 'killed';
+      case 'RUNNING':
+        return 'running';
+      case 'ERROR':
+        return 'error';
+      case 'SUCCEEDED':
+        var counterGroups = dag.get('counterGroups');
+        var numFailedTasks = this.getCounterValueForDag(counterGroups,
+          dag.get('id'), 'org.apache.tez.common.counters.DAGCounter',
+          'NUM_FAILED_TASKS'
+        ); 
 
-		if (numFailedTasks > 0) {
-			return 'warning';
-		}
+        if (numFailedTasks > 0) {
+          return 'warning';
+        }
 
-		return 'success';
-	},
+        return 'success';
+      default:
+        return 'submitted';
+    }
+  },
 
 	getCounterValueForDag: function(counterGroups, dagID, counterGroupName, counterName) {
 		if (!counterGroups) {
@@ -53,5 +63,14 @@ App.Helpers.misc = {
 		if (!counter) return 0;
 
 		return counter.get('value');
-	}
+	},
+
+  isValidDagStatus: function(status) {
+    return $.inArray(status, ['SUBMITTED', 'INITING', 'RUNNING', 'SUCCEEDED',
+      'KILLED', 'FAILED', 'ERROR']) != -1;
+  },
+
+  isValidTaskStatus: function(status) {
+    return $.inArray(status, ['RUNNING', 'SUCCEEDED', 'FAILED', 'KILLED']) != -1;
+  }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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 d34c90e..b650705 100644
--- a/tez-ui/app/scripts/mixins/paginated_content.js
+++ b/tez-ui/app/scripts/mixins/paginated_content.js
@@ -15,22 +15,11 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-var modelToATSType = {
-	dag: 'TEZ_DAG_ID',
-	task: 'TEZ_TASK_ID',
-	vertex: 'TEZ_VERTEX_ID',
-	taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
-};
-
-var childEntityTypeForParent = {
-	dag: 'task',
-	task: 'taskAttempt'
-}
 
 App.PaginatedContentMixin = Em.Mixin.create({
 	count: 5,
 	
-	fromID: '',
+	fromID: null,
 
 	/* 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 
@@ -46,10 +35,6 @@ App.PaginatedContentMixin = Em.Mixin.create({
   _paginationFilters: {},
 	loading: true,
 
-  getChildEntityType: function(parentType) {
-    return childEntityTypeForParent[parentType];
-  },
-
   sortedContent: function() {
     var sorted = Em.ArrayController.create({
       model: this.get('entities'),
@@ -62,7 +47,6 @@ App.PaginatedContentMixin = Em.Mixin.create({
 
 	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){
@@ -83,7 +67,7 @@ App.PaginatedContentMixin = Em.Mixin.create({
 		this.set('navIDs.prevIDs', []);
 		this.set('navIDs.currentID', '');
 		this.set('navIDs.nextID', '');
-		this.set('fromID', '');
+		this.set('fromID', null);
 	},
 
 	updatePagination: function(dataArray) {
@@ -153,9 +137,6 @@ App.PaginatedContentMixin = Em.Mixin.create({
 		var secondary = f.secondary || {};
 
 		primary = this._concatFilters(primary);
-		if (Em.empty(primary)) {
-			primary = modelToATSType[this.get('parentEntityType')] + ':' + this.get('id');
-		}
 
 		secondary = this._concatFilters(secondary);
 

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/router.js b/tez-ui/app/scripts/router.js
index 0e800ac..c2bcca8 100644
--- a/tez-ui/app/scripts/router.js
+++ b/tez-ui/app/scripts/router.js
@@ -32,7 +32,7 @@ App.Router.map(function() {
     this.route('swimlane');
   });
 	
-	this.resource('tasks', {path: '/tasks/:dag_id'});
+	this.resource('tasks', {path: '/tasks'});
 	this.resource('task', {path: '/task/:task_id'}, function(){
 		this.route('attempts');
 		this.route('counters');
@@ -62,39 +62,29 @@ App.ApplicationRoute = Em.Route.extend({
 });*/
 
 App.DagsRoute = Em.Route.extend({
-	queryParams:  {
-		count: {
-			refreshModel: true,
-			replace: true
-		},
-		fromID: {
-			refreshModel: true,
-			replace: true
-		},
-		fromTS: {
-			refreshModel: true,
-			replace: true,
-		},
-		user: {
-			refreshModel: true,
-			replace: true
-		}
-	},
-
-	model: function(params) {
-		var controllerClass = this.controllerFor('dags');
-		var queryParams = controllerClass.getFilterParams(params);
-
-		//TODO remove this
-		this.store.unloadAll('dag');
-		this.store.unloadAll('counterGroup');
-		this.store.unloadAll('counter');
-		return this.store.findQuery('dag', queryParams);
-	},
+  queryParams:  {
+    count: {
+      refreshModel: true,
+      replace: true
+    },
+    fromID: {
+      refreshModel: true,
+      replace: true
+    },
+    user: {
+      refreshModel: true,
+      replace: true
+    },
+    status: {
+    refreshModel: true,
+      replace: true
+    }
+  },
 
-	setupController: function(controller, model) {
-		this._super(controller, model);
-	},
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  },
 });
 
 App.DagRoute = Em.Route.extend({
@@ -122,20 +112,25 @@ App.DagSwimlaneRoute = Em.Route.extend({
 });
 
 App.TasksRoute = Em.Route.extend({
-	model: function(params) {
-		var controllerClass = this.controllerFor('tasks');
-		var queryParams = controllerClass.getFilterParams(params);
-		
-		//TODO: fix this
-		this.store.unloadAll('task');
-		this.store.unloadAll('counterGroup');
-		this.store.unloadAll('counter');
-		return this.store.findQuery('task', queryParams);
-	},
+  queryParams: {
+    status: {
+      refreshModel: true,
+      replace: true
+    },
+    parentType: {
+      refreshModel: true,
+      replace: true
+    },
+    parentID: {
+      refreshModel: true,
+      replace: true
+    }
+  },
 
-	setupController: function(controller, model) {
-		this._super(controller, model);
-	}
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  }
 });
 
 App.TaskRoute = Em.Route.extend({
@@ -171,4 +166,64 @@ App.VertexSwimlaneRoute = Em.Route.extend({
   setupController: function(controller, model) {
     this._super(controller, model);
   }
+});
+
+App.DagTasksRoute = Em.Route.extend({
+  queryParams: {
+    status: {
+      refreshModel: true,
+      replace: true
+    },
+    vertex_id: {
+      refreshModel: true,
+      replace: true
+    }
+  },
+
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  }
+});
+
+App.DagVerticesRoute = Em.Route.extend({
+  queryParams: {
+    status: {
+      refreshModel: true,
+      replace: true
+    }
+  },
+
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  }
+});
+
+App.VertexTasksRoute = Em.Route.extend({
+  queryParams: {
+    status: {
+      refreshModel: true,
+      replace: true
+    }
+  },
+
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  }
+});
+
+App.TaskAttemptsRoute = Em.Route.extend({
+  queryParams: {
+    status: {
+      refreshModel: true,
+      replace: true
+    }
+  },
+
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadData();
+  }
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/styles/main.less
----------------------------------------------------------------------
diff --git a/tez-ui/app/styles/main.less b/tez-ui/app/styles/main.less
index 29581d7..2c1714a 100644
--- a/tez-ui/app/styles/main.less
+++ b/tez-ui/app/styles/main.less
@@ -1,3 +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.
+ */
+
 @import "../bower_components/font-awesome/less/font-awesome";
 
 .fa-icon(@name) {
@@ -105,11 +123,16 @@
 		color: @success-color;
 	}
 
-	&.failure {
+	&.failed {
 		.fa-icon(exclamation-circle);
 		color: @error-color;
 	}
 
+  &.killed {
+    .fa-icon(exclamation-circle);
+    color: @warning-color;
+  }
+
 	&.warning {
 		.fa-icon(exclamation-triangle);
 		color: @warning-color;

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 2524b6e..a29906b 100644
--- a/tez-ui/app/templates/components/extended-table/filter-cell.hbs
+++ b/tez-ui/app/templates/components/extended-table/filter-cell.hbs
@@ -2,8 +2,6 @@
   <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/c327ac6f/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 e48e58d..36a44fb 100644
--- a/tez-ui/app/templates/dag/index.hbs
+++ b/tez-ui/app/templates/dag/index.hbs
@@ -26,30 +26,11 @@
 						{{status}}
 						<i {{bind-attr class=':task-status taskIconStatus'}}></i>
 					</td>
-				</tr>
-				<tr>
-					<td>Total Tasks</td>
-					<td>{{totalTasks}}</td>
-				</tr>
-				<tr>
-					<td>Successful Tasks</td>
-					<td>{{sucessfulTasks}}</td>
-				</tr>
-				<tr>
-					<td>Failed Tasks</td>
-					<td>
-						{{failedTasks}}
-					</td>
-					<td>
-						{{#if hasFailedTasks}}
-							{{!TODO: place link to the tasks that failed}}
-							{{#link-to 'tasks' id}}Failed Tasks{{/link-to}}
-						{{/if}}
-					</td>
-				</tr>
-				<tr>
-					<td>Killed Tasks</td>
-					<td>{{killedTasks}}</td>
+          <td>
+            {{#if hasFailedTasks}}
+              <a href='{{unbound failedTasksLink}}'>FailedTasks</a>
+            {{/if}}
+          </td>
 				</tr>
 			</tbody>
 		</table>

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index a342ae1..bbe9b40 100644
--- a/tez-ui/app/templates/dag/tasks.hbs
+++ b/tez-ui/app/templates/dag/tasks.hbs
@@ -19,11 +19,10 @@
 		columnsBinding="columns"
 		contentBinding="sortedContent"
 		forceFillColumns=true
-		filtersBinding='filterValues'
 		hasFilter=true
+    onFilterUpdated='filterUpdated'
 	}}
 	</div>
 {{else}}
 	{{partial 'utils/loadingSpinner'}}	
 {{/unless}}
-	{{!todo remove unnecessary stuff}}

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 6bacc38..04f631b 100644
--- a/tez-ui/app/templates/dag/vertices.hbs
+++ b/tez-ui/app/templates/dag/vertices.hbs
@@ -19,8 +19,8 @@
 		columnsBinding="columns"
 		contentBinding="sortedContent"
 		forceFillColumns=true
-		filtersBinding='filterValues'
 		hasFilter=true
+    onFilterUpdated='filterUpdated'
 	}}
 	</div>
 {{else}}

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/templates/dags.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/dags.hbs b/tez-ui/app/templates/dags.hbs
index 647ef42..4ecf3f3 100644
--- a/tez-ui/app/templates/dags.hbs
+++ b/tez-ui/app/templates/dags.hbs
@@ -19,40 +19,37 @@
 {{partial 'utils/pageHeader'}}
 
 {{#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='margin-small'>
+    <span class='align-left'>
+      {{page-nav-component
+        hasPrev=hasPrev
+        hasNext=hasNext
+        navNext='navigateNext'
+        navPrev='navigatePrev'
+        navFirst='navigateFirst'
+      }}
+    </span>
+    <span class='align-right'>
+      Number of Dags to Show
+      {{view Ember.Select 
+        content=countOptions 
+        value=count
+      }}
+    </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>
+  <div class='table-container'>
+    {{extended-table-component
+      hasFooter=false
+      enableContentSelection=true
+      columnsBinding='columns'
+      contentBinding='sortedContent'
+      forceFillColumns=true
+      hasFilter=true
+      onFilterUpdated='filterUpdated'
+    }}
+  </div>
 {{else}}
-	{{partial 'utils/loadingSpinner'}}	
+  {{partial 'utils/loadingSpinner'}}
 {{/unless}}

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index 6bacc38..04f631b 100644
--- a/tez-ui/app/templates/task/attempts.hbs
+++ b/tez-ui/app/templates/task/attempts.hbs
@@ -19,8 +19,8 @@
 		columnsBinding="columns"
 		contentBinding="sortedContent"
 		forceFillColumns=true
-		filtersBinding='filterValues'
 		hasFilter=true
+    onFilterUpdated='filterUpdated'
 	}}
 	</div>
 {{else}}

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/tez-ui/app/templates/vertex.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex.hbs b/tez-ui/app/templates/vertex.hbs
index f083e2c..54d41fb 100644
--- a/tez-ui/app/templates/vertex.hbs
+++ b/tez-ui/app/templates/vertex.hbs
@@ -18,13 +18,6 @@
 
 {{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'>

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index ce21749..ba2955e 100644
--- a/tez-ui/app/templates/vertex/index.hbs
+++ b/tez-ui/app/templates/vertex/index.hbs
@@ -46,6 +46,11 @@
           <td>
             {{failedTasks}}
           </td>
+          <td>
+            {{#if hasFailedTasks}}
+              <a href='{{unbound failedTasksLink}}'>FailedTasks</a>
+            {{/if}}
+          </td>
         </tr>
         <tr>
           <td>Killed Tasks</td>

http://git-wip-us.apache.org/repos/asf/tez/blob/c327ac6f/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
index eac99a1..7224117 100644
--- a/tez-ui/app/templates/vertex/tasks.hbs
+++ b/tez-ui/app/templates/vertex/tasks.hbs
@@ -37,8 +37,8 @@
     columnsBinding="columns"
     contentBinding="sortedContent"
     forceFillColumns=true
-    filtersBinding='filterValues'
     hasFilter=true
+    onFilterUpdated='filterUpdated'
   }}
   </div>
 {{else}}


Mime
View raw message