tez-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From prak...@apache.org
Subject tez git commit: TEZ-2274. Tez UI: full data loading, client side search and sort for other pages (Sreenath Somarajapuram via pramachandran)
Date Fri, 10 Apr 2015 13:56:56 GMT
Repository: tez
Updated Branches:
  refs/heads/master 24f66a0f8 -> f38282834


TEZ-2274. Tez UI: full data loading, client side search and sort for other pages (Sreenath Somarajapuram via pramachandran)


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

Branch: refs/heads/master
Commit: f38282834c7649e60dc20f2c4306c03ba6f01cf8
Parents: 24f66a0
Author: Prakash Ramachandran <pramachandran@hortonworks.com>
Authored: Fri Apr 10 19:25:51 2015 +0530
Committer: Prakash Ramachandran <pramachandran@hortonworks.com>
Committed: Fri Apr 10 19:25:51 2015 +0530

----------------------------------------------------------------------
 CHANGES.txt                                     |   1 +
 .../controllers/dag-task-attempts-controller.js | 221 +++++++----------
 .../webapp/app/scripts/controllers/dag_tasks.js |   8 -
 .../app/scripts/controllers/dag_vertices.js     | 186 ++++++--------
 .../app/scripts/controllers/dags_controller.js  |   8 +
 .../task_task_attempts_controller.js            | 197 ++++++---------
 .../controllers/tez-app-dags-controller.js      | 200 ++++++---------
 .../vertex-additionals-controller.js            |  51 ++--
 .../vertex_task_attempts_controller.js          | 199 ++++++---------
 .../controllers/vertex_tasks_controller.js      | 243 +++++++------------
 .../app/scripts/mixins/column-selector-mixin.js |   3 +-
 tez-ui/src/main/webapp/app/scripts/router.js    |  46 +---
 .../basic-table/vertex-configurations-cell.hbs  |  31 +++
 13 files changed, 547 insertions(+), 847 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index fbdcb17..731dedd 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,7 @@ INCOMPATIBLE CHANGES
   TEZ-1993. Implement a pluggable InputSizeEstimator for grouping fairly
 
 ALL CHANGES:
+  TEZ-2274. Tez UI: full data loading, client side search and sort for other pages
   TEZ-2301. Switch Tez Pre-commit builds to use tezqa user.
   TEZ-2299. Invalid dag creation in MRRSleepJob post TEZ-2293.
   TEZ-2290. Scale memory for Default Sorter down to a max of 2047 MB if configured higher.

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
index 6617c10..2dda5f4 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag-task-attempts-controller.js
@@ -16,92 +16,41 @@
  * limitations under the License.
  */
 
-App.DagTaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  // Required by the PaginatedContentMixin
-  needs: 'dag',
-  childEntityType: 'taskAttempt',
+App.DagTaskAttemptsController = App.TablePageController.extend({
 
   controllerName: 'DagTaskAttemptsController',
+  needs: "dag",
 
-  queryParams: {
-    status_filter: 'status',
-    vertex_name_filter: 'vertex_name',
-  },
-  status_filter: null,
-  vertex_name_filter: null,
-
-  loadData: function() {
-    var primaryFilter = {
-      TEZ_DAG_ID : this.get('controllers.dag.id')
-    };
-    if (!!this.vertex_name_filter) {
-      var vertexIdMap = this.get('controllers.dag.vertexIdToNameMap');
-      var vertexId = App.Helpers.misc.getVertexIdFromName(vertexIdMap, this.vertex_name_filter)
-        || 'unknown';
-      primaryFilter = { TEZ_VERTEX_ID : vertexId };
-    }
-
-    var filters = {
-      primary: primaryFilter,
-      secondary: {
-        status: this.status_filter
-      }
-    }
-    this.setFiltersAndLoadEntities(filters);
-  },
+  entityType: 'taskAttempt',
+  filterEntityType: 'dag',
+  filterEntityId: Ember.computed.alias('controllers.dag.id'),
 
-  load: function () {
-    var dag = this.get('controllers.dag.model'),
-        controller = this.get('controllers.dag'),
-        t = this;
-    t.set('loading', true);
-    dag.reload().then(function () {
-      return controller.loadAdditional(dag);
-    }).then(function () {
-      t.resetNavigation();
-      t.loadEntities();
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
+  beforeLoad: function () {
+    var dagController = this.get('controllers.dag'),
+        model = dagController.get('model');
+    return model.reload().then(function () {
+      return dagController.loadAdditional(model);
     });
-  }.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();
-    }
   },
 
-  updateLoading: function () {
-    var dagController = this.get('controllers.dag'),
-        model = this.get('controllers.dag.model'),
-        that = this,
-        dagStatus = that.get('controllers.dag.status');
-
-    dagController.loadAdditional(model).then(function () {
-      that.get('entities').forEach(function (attempt) {
-
-        var attemptStatus = App.Helpers.misc
-          .getFixedupDisplayStatus(attempt.get('status'));
-        if (attemptStatus == 'RUNNING' &&
-          App.Helpers.misc.isStatusInUnsuccessful(dagStatus)) {
-          attemptStatus = 'KILLED'
-        }
-        if (attemptStatus != attempt.get('status')) {
-          attempt.set('status', attemptStatus);
-        }
-      });
-
-      that.set('loading', false);
+  afterLoad: function () {
+    var data = this.get('data'),
+        isUnsuccessfulDag = App.Helpers.misc.isStatusInUnsuccessful(
+          this.get('controllers.dag.status')
+        );
+
+    data.forEach(function (attempt) {
+      var attemptStatus = App.Helpers.misc
+        .getFixedupDisplayStatus(attempt.get('status'));
+      if (attemptStatus == 'RUNNING' && isUnsuccessfulDag) {
+        attemptStatus = 'KILLED'
+      }
+      if (attemptStatus != attempt.get('status')) {
+        attempt.set('status', attemptStatus);
+      }
     });
+
+    return this._super();
   },
 
   defaultColumnConfigs: function() {
@@ -111,83 +60,98 @@ App.DagTaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentM
       {
         id: 'taskId',
         headerCellName: 'Task Index',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'task' view.cellContent.taskId class='ember-table-content'}}{{view.cellContent.displayId}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'taskID',
         getCellContent: function (row) {
           var taskId = row.get('taskID'),
               idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
           return {
-            taskId: taskId,
-            displayId: taskId.indexOf(idPrefix) == 0 ? taskId.substr(idPrefix.length) : taskId
+            linkTo: 'task',
+            entityId: taskId,
+            displayText: taskId.indexOf(idPrefix) == 0 ? taskId.substr(idPrefix.length) : taskId
           };
+        },
+        getSearchValue: function (row) {
+          var id = row.get('taskID'),
+              idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
+          return id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id;
         }
       },
       {
         id: 'attemptNo',
         headerCellName: 'Attempt No',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'taskAttempt' view.cellContent.attemptID class='ember-table-content'}}{{view.cellContent.attemptNo}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'id',
         getCellContent: function(row) {
-          var attemptID = row.get('id') || '',
-              attemptNo = attemptID.split(/[_]+/).pop();
+          var attemptID = row.get('id') || '';
           return {
-            attemptNo: attemptNo,
-            attemptID: attemptID
+            linkTo: 'taskAttempt',
+            displayText: attemptID.split(/[_]+/).pop(),
+            entityId: attemptID
           };
+        },
+        getSearchValue: function (row) {
+          var attemptID = row.get('id') || '';
+          return attemptID.split(/[_]+/).pop();
         }
       },
       {
         id: 'vertexName',
         headerCellName: 'Vertex Name',
-        filterID: 'vertex_name_filter',
+        contentPath: 'vertexID',
         getCellContent: function(row) {
           var vertexId = row.get('vertexID');
           return vertexIdToNameMap[vertexId] || vertexId;
+        },
+        getSearchValue: function (row) {
+          var vertexId = row.get('vertexID');
+          return vertexIdToNameMap[vertexId] || vertexId;
+        },
+        getSortValue: function (row) {
+          var vertexId = row.get('vertexID');
+          return vertexIdToNameMap[vertexId] || vertexId;
         }
       },
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
-        }
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
-        }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
       },
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.taskAttemptStatusUIOptions,
-        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>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
-          var status = row.get('status');
+          var status = App.Helpers.misc.getFixedupDisplayStatus(row.get('status'));
           return {
             status: status,
             statusIcon: App.Helpers.misc.getStatusClassForEntity(status)
@@ -207,34 +171,23 @@ App.DagTaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentM
       {
         id: 'actions',
         headerCellName: 'Actions',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-            {{#link-to "taskAttempt.counters" view.cellContent}}counters{{/link-to}}&nbsp;\
-            </span>'
-            )
-        }),
-        contentPath: 'id'
+        templateName: 'components/basic-table/linked-cell',
+        searchAndSortable: false,
+        contentPath: 'id',
+        getCellContent: function(row) {
+          var attemptID = row.get('id') || '';
+          return {
+            linkTo: 'taskAttempt.counters',
+            displayText: 'counters',
+            entityId: attemptID
+          };
+        }
       },
       {
         id: 'logs',
         headerCellName: 'Logs',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-              {{#unless view.cellContent.notAvailable}}\
-                Not Available\
-              {{else}}\
-                {{#if view.cellContent.viewUrl}}\
-                  <a target="_blank" href="//{{unbound view.cellContent.viewUrl}}">View</a>\
-                  &nbsp;\
-                {{/if}}\
-                {{#if view.cellContent.downloadUrl}}\
-                  <a target="_blank" href="{{unbound view.cellContent.downloadUrl}}?start=0" download type="application/octet-stream">Download</a>\
-                {{/if}}\
-              {{/unless}}\
-            </span>')
-        }),
+        templateName: 'components/basic-table/logs-cell',
+        searchAndSortable: false,
         getCellContent: function(row) {
           var yarnAppState = that.get('controllers.dag.yarnAppState'),
               suffix = "/syslog_" + row.get('id'),

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
index 761e0b6..56a499a 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_tasks.js
@@ -53,14 +53,6 @@ App.DagTasksController = App.TablePageController.extend({
     return this._super();
   },
 
-  columns: function() {
-    var visibleColumnConfigs = this.get('columnConfigs').filter(function (column) {
-      return this.visibleColumnIds[column.id];
-    }, this);
-
-    return App.Helpers.misc.createColumnDescription(visibleColumnConfigs);
-  }.property('visibleColumnIds'),
-
   defaultColumnConfigs: function() {
     var that = this,
         vertexIdToNameMap = this.get('controllers.dag.vertexIdToNameMap') || {};

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
index 44ffd1a..eec502b 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dag_vertices.js
@@ -16,71 +16,49 @@
  * limitations under the License.
  */
 
-App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  needs: "dag",
-
+App.DagVerticesController = App.TablePageController.extend({
   controllerName: 'DagVerticesController',
+  needs: "dag",
 
-  // required by the PaginatedContentMixin
-  childEntityType: 'vertex',
-
-  count: 50,
+  entityType: 'vertex',
+  filterEntityType: 'dag',
+  filterEntityId: Ember.computed.alias('controllers.dag.id'),
 
-  queryParams: {
-    status_filter: 'status'
+  beforeLoad: function () {
+    var dagController = this.get('controllers.dag'),
+        model = dagController.get('model');
+    return model.reload().then(function () {
+      return dagController.loadAdditional(model);
+    });
   },
 
-  status_filter: null,
+  afterLoad: function () {
+    var data = this.get('data'),
+        runningVerticesIdx,
+        isUnsuccessfulDag = App.Helpers.misc.isStatusInUnsuccessful(
+          this.get('controllers.dag.status')
+        );
 
-  loadData: function() {
-    var filters = {
-      primary: {
-        TEZ_DAG_ID: this.get('controllers.dag.id')
-      },
-      secondary: {
-        status: this.status_filter
-      }
+    if(isUnsuccessfulDag) {
+      data.filterBy('status', 'RUNNING').forEach(function (vertex) {
+        vertex.set('status', 'KILLED');
+      });
     }
-    this.setFiltersAndLoadEntities(filters);
-  },
 
-  load: function () {
-    var dag = this.get('controllers.dag.model'),
-        controller = this.get('controllers.dag'),
-        t = this;
-    t.set('loading', true);
-    dag.reload().then(function () {
-      return controller.loadAdditional(dag);
-    }).then(function () {
-      t.resetNavigation();
-      t.loadEntities();
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
-    });
-  }.observes('count'),
+    this._loadProgress(data);
 
-  loadAdditional: function() {
-    var defer = Em.RSVP.defer();
+    return this._super();
+  },
 
+  // Load progress in parallel
+  _loadProgress: function (vertices) {
     var that = this,
-        vertices = this.get('entities');
-
-    var dagStatus = this.get('controllers.dag.status');
-    if (App.Helpers.misc.isStatusInUnsuccessful(dagStatus)) {
-      vertices.filterBy('status', 'RUNNING')
-        .forEach(function(item) {
-          item.set('status', 'KILLED');
-        });
-    }
-
-    var runningVerticesIdx = vertices
+        runningVerticesIdx = vertices
       .filterBy('status', 'RUNNING')
       .map(function(item) {
         return item.get('id').split('_').splice(-1).pop();
       });
+
     if (runningVerticesIdx.length > 0) {
       this.store.unloadAll('vertexProgress');
       this.store.findQuery('vertexProgress', {
@@ -96,41 +74,33 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
         });
       }).catch(function(error) {
         Em.Logger.debug("failed to fetch vertex progress")
-      }).finally(function(){
-        defer.resolve();
-      })
-    } else {
-      defer.resolve();
+      });
     }
-
-    return defer.promise;
   },
 
-  actions : {
-    filterUpdated: function(filterID, value) {
-      // any validations required goes here.
-      if (!!value) {
-        this.set(filterID, value);
-      } else {
-        this.set(filterID, null);
+  defaultColumnConfigs: function() {
+    var that = this;
+
+    function onProgressChange() {
+      var progress = this.get('vertex.progress'),
+          pct;
+      if (Ember.typeOf(progress) === 'number') {
+        pct = App.Helpers.number.fractionToPercentage(progress);
+        this.set('progress', pct);
       }
-      this.loadData();
     }
-  },
 
-  defaultColumnConfigs: function() {
     return [
       {
         id: 'vertexName',
         headerCellName: 'Vertex Name',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'vertex' view.cellContent.id class='ember-table-content'}}{{view.cellContent.name}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'name',
         getCellContent: function(row) {
           return {
-            id: row.get('id'),
-            name: row.get('name')
+            linkTo: 'vertex',
+            entityId: row.get('id'),
+            displayText: row.get('name')
           };
         }
       },
@@ -142,33 +112,45 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
-        }
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
         }
       },
       {
         id: 'firstTaskStartTime',
         headerCellName: 'First Task Start Time',
+        contentPath: 'firstTaskStartTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('firstTaskStartTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('firstTaskStartTime'));
         }
       },
       {
@@ -184,45 +166,27 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.vertexStatusUIOptions,
-        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}}\
-            {{#if view.cellContent.progress}} {{bs-badge content=view.cellContent.progress}}{{/if}}</span>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
-          var pct,
-              vertexStatus = row.get('status');
-          if (Ember.typeOf(row.get('progress')) === 'number') {
-            pct = App.Helpers.number.fractionToPercentage(row.get('progress'));
+          var status = row.get('status'),
+              content = Ember.Object.create({
+                vertex: row,
+                status: status,
+                statusIcon: App.Helpers.misc.getStatusClassForEntity(status)
+              });
+
+          if(status == 'RUNNING') {
+            row.addObserver('progress', content, onProgressChange);
           }
-
-          return {
-            status: vertexStatus,
-            statusIcon: App.Helpers.misc.getStatusClassForEntity(vertexStatus),
-            progress: pct
-          };
+          return content;
         }
       },
       {
         id: 'configurations',
         headerCellName: 'Source/Sink Configs',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            " {{#if view.cellContent.linkToAdditionals}}\
-                {{#link-to 'vertex.additionals' view.cellContent.vertexId class='ember-table-content'}}View sources & sinks{{/link-to}}\
-              {{else}}{{#if view.cellContent.inputId}}\
-                {{#link-to 'input.configs' view.cellContent.vertexId view.cellContent.inputId class='ember-table-content'}}View source configs{{/link-to}}\
-              {{else}}{{#if view.cellContent.outputId}}\
-                {{#link-to 'output.configs' view.cellContent.vertexId view.cellContent.outputId class='ember-table-content'}}View sink configs{{/link-to}}\
-              {{else}}\
-                <span class='ember-table-content'>No source or sink</span>\
-              {{/if}}{{/if}}{{/if}}")
-        }),
+        templateName: 'components/basic-table/vertex-configurations-cell',
+        searchAndSortable: false,
         getCellContent: function(row) {
           var firstInputId = row.get('inputs.content.0.id'),
               firstOutputId = row.get('outputs.content.0.id');

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
index 66a33f1..9968a6a 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
@@ -262,4 +262,12 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.C
     );
   }.property(),
 
+  columns: function() {
+    var visibleColumnConfigs = this.get('columnConfigs').filter(function (column) {
+      return this.visibleColumnIds[column.id];
+    }, this);
+
+    return App.Helpers.misc.createColumnsFromConfigs(visibleColumnConfigs);
+  }.property('visibleColumnIds'),
+
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
index d30cb21..06e311f 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/task_task_attempts_controller.js
@@ -16,85 +16,43 @@
  * limitations under the License.
  */
 
-App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  // required by the PaginatedContentMixin
-  childEntityType: 'task_attempt',
+App.TaskAttemptsController = App.TablePageController.extend({
 
   controllerName: 'TaskAttemptsController',
+  needs: "task",
 
-  needs: 'task',
+  entityType: 'taskAttempt',
+  filterEntityType: 'task',
+  filterEntityId: Ember.computed.alias('controllers.task.id'),
 
-  queryParams: {
-    status_filter: 'status'
-  },
-  status_filter: null,
-
-  loadData: function() {
-    var filters = {
-      primary: {
-        TEZ_TASK_ID: this.get('controllers.task.id')
-      },
-      secondary: {
-        status: this.status_filter
-      }
-    }
-    this.setFiltersAndLoadEntities(filters);
+  beforeLoad: function () {
+    var taskController = this.get('controllers.task'),
+        model = taskController.get('model');
+    return model.reload().then(function () {
+      return taskController.loadAdditional(model);
+    });
   },
 
-  loadEntities: function () {
-    var that = this;
-    var childEntityType = this.get('childEntityType');
-    var defaultErrMsg = 'Error while loading %@.'
-      .fmt(childEntityType);
-
-    that.set('loading', true);
-    this.get('store').unloadAll(childEntityType);
-    this.get('store').findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
-      var loaders = [];
-      try {
-        var loader = Em.tryInvoke(that, 'loadAdditional');
-        if (!!loader) {
-          loaders.push(loader);
+  afterLoad: function () {
+    var loaders = [],
+        that = this;
+
+    App.Helpers.misc.removeRecord(that.store, 'dag', that.get('controllers.task.dagID'));
+
+    var appDetailFetcher = that.store.find('dag', that.get('controllers.task.dagID')).
+      then(function (dag) {
+        App.Helpers.misc.removeRecord(that.store, 'appDetail', dag.get('applicationId'));
+        return that.store.find('appDetail', dag.get('applicationId'));
+      }).
+      then(function(appDetail) {
+        var appState = appDetail.get('appState');
+        if (appState) {
+          that.set('yarnAppState', appState);
         }
-      } catch(error) {
-        Em.Logger.error("Exception invoking additional load", error);
-      }
-
-      App.Helpers.misc.removeRecord(that.store, 'dag', that.get('controllers.task.dagID'));
-      var appDetailFetcher = that.store.find('dag', that.get('controllers.task.dagID')).
-        then(function (dag) {
-          App.Helpers.misc.removeRecord(that.store, 'appDetail', dag.get('applicationId'));
-          return that.store.find('appDetail', dag.get('applicationId'));
-        }).
-        then(function(appDetail) {
-          var appState = appDetail.get('appState');
-          if (appState) {
-            that.set('yarnAppState', appState);
-          }
-        });
-      loaders.push(appDetailFetcher);
-      Em.RSVP.allSettled(loaders).then(function(){
-        that.set('entities', entities);
-        that.set('loading', false);
       });
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
-    });
-  },
+    loaders.push(appDetailFetcher);
 
-  actions : {
-    filterUpdated: function(filterID, value) {
-      // any validations required goes here.
-      if (!!value) {
-        this.set(filterID, value);
-      } else {
-        this.set(filterID, null);
-      }
-      this.loadData();
-    }
+    return Em.RSVP.allSettled(loaders);
   },
 
   defaultColumnConfigs: function() {
@@ -103,72 +61,74 @@ App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixi
       {
         id: 'id',
         headerCellName: 'Attempt Index',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'taskAttempt' view.cellContent.id class='ember-table-content'}}{{view.cellContent.displayId}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'id',
         getCellContent: function (row) {
           var id = row.get('id'),
               idPrefix = 'attempt_%@_'.fmt(row.get('dagID').substr(4));
           return {
-            id: id,
-            displayId: id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id
+            linkTo: 'taskAttempt',
+            entityId: id,
+            displayText: id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id
           };
         }
       },
       {
         id: 'attemptNo',
         headerCellName: 'Attempt No',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'taskAttempt' view.cellContent.attemptID class='ember-table-content'}}{{view.cellContent.attemptNo}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'id',
         getCellContent: function(row) {
-          var attemptID = row.get('id') || '',
-              attemptNo = attemptID.split(/[_]+/).pop();
+          var attemptID = row.get('id') || '';
           return {
-            attemptNo: attemptNo,
-            attemptID: attemptID
+            linkTo: 'taskAttempt',
+            displayText: attemptID.split(/[_]+/).pop(),
+            entityId: attemptID
           };
+        },
+        getSearchValue: function (row) {
+          var attemptID = row.get('id') || '';
+          return attemptID.split(/[_]+/).pop();
         }
       },
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
-        }
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
-        }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
       },
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.taskAttemptStatusUIOptions,
-        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>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
           var status = App.Helpers.misc.getFixedupDisplayStatus(row.get('status'));
           return {
@@ -190,34 +150,23 @@ App.TaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixi
       {
         id: 'actions',
         headerCellName: 'Actions',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-            {{#link-to "taskAttempt.counters" view.cellContent}}counters{{/link-to}}&nbsp;\
-            </span>'
-            )
-        }),
-        contentPath: 'id'
+        templateName: 'components/basic-table/linked-cell',
+        searchAndSortable: false,
+        contentPath: 'id',
+        getCellContent: function(row) {
+          var attemptID = row.get('id') || '';
+          return {
+            linkTo: 'taskAttempt.counters',
+            displayText: 'counters',
+            entityId: attemptID
+          };
+        }
       },
       {
         id: 'logs',
         headerCellName: 'Logs',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-              {{#unless view.cellContent.notAvailable}}\
-                Not Available\
-              {{else}}\
-                {{#if view.cellContent.viewUrl}}\
-                  <a target="_blank" href="//{{unbound view.cellContent.viewUrl}}">View</a>\
-                  &nbsp;\
-                {{/if}}\
-                {{#if view.cellContent.downloadUrl}}\
-                  <a target="_blank" href="{{unbound view.cellContent.downloadUrl}}?start=0" download type="application/octet-stream">Download</a>\
-                {{/if}}\
-              {{/unless}}\
-            </span>')
-        }),
+        templateName: 'components/basic-table/logs-cell',
+        searchAndSortable: false,
         getCellContent: function(row) {
           var yarnAppState = that.get('yarnAppState'),
               suffix = "/syslog_" + row.get('id'),

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
index b448ca8..22aaaf9 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
@@ -16,129 +16,62 @@
  * limitations under the License.
  */
 
-App.TezAppDagsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  needs: "tezApp",
+App.TezAppDagsController = App.TablePageController.extend({
 
   controllerName: 'TezAppDagsController',
+  needs: "tezApp",
 
-  // required by the PaginatedContentMixin
-  childEntityType: 'dag',
+  entityType: 'dag',
+  filterEntityType: 'tezApp',
+  filterEntityId: Ember.computed.alias('appId'),
 
-  queryParams: {
-    dagName_filter: 'dagName',
-    status_filter: 'status',
-    user_filter: 'user'
-  },
-  dagName_filter: null,
-  status_filter: null,
-  user_filter: null,
+  afterLoad: function () {
+    var data = this.get('data'),
+        loaders = [],
+        store = this.get('store'),
+        record,
+        fetcher;
 
-  loadData: function() {
-    var filters = {
-      primary: {
-        applicationId: this.get('appId'),
-      },
-      secondary: {
-        user: this.user_filter,
-        status: this.status_filter,
-        dagName: this.dagName_filter
-      }
-    };
-    this.setFiltersAndLoadEntities(filters);
-  },
-
-  loadEntities: function() {
-    var that = this,
-    store = this.get('store'),
-    childEntityType = this.get('childEntityType'),
-    fetcher,
-    record;
-    var defaultErrMsg = 'Error while loading dag info.';
+    data.forEach(function (dag) {
 
-    that.set('loading', true);
-    store.unloadAll(childEntityType);
-    store.unloadAll('dagProgress');
-
-    store.findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
-      var loaders = [];
-      entities.forEach(function (dag) {
-        var appId = dag.get('applicationId');
-        if(appId) {
-          // Pivot attempt selection logic
-          record = store.getById('appDetail', appId);
-          if(record && !App.Helpers.misc.isStatusInUnsuccessful(record.get('appState'))) {
-            store.unloadRecord(record);
-          }
-          fetcher = store.find('appDetail', appId).then(function (app) {
-            dag.set('appDetail', app);
-            if (dag.get('status') === 'RUNNING') {
-              dag.set('status', App.Helpers.misc.getRealStatus(
-                dag.get('status'),
-                app.get('appState'),
-                app.get('finalAppStatus')
-              ));
-              App.Helpers.misc.removeRecord(store, 'tezApp', 'tez_' + appId);
-            }
-            return store.find('tezApp', 'tez_' + appId).then(function (app) {
-              dag.set('tezApp', app);
-            });
+      var appId = dag.get('applicationId');
+      if(appId) {
+        //Load tezApp details
+        if (dag.get('status') === 'RUNNING') {
+          App.Helpers.misc.removeRecord(store, 'dagProgress', dag.get('id'));
+          fetcher = store.find('dagProgress', dag.get('id'), {
+            appId: dag.get('applicationId'),
+            dagIdx: dag.get('idx')
+          })
+          .then(function(dagProgressInfo) {
+            dag.set('progress', dagProgressInfo.get('progress'));
+          })
+          .catch(function(error) {
+            Em.Logger.error('Failed to fetch dagProgress' + error);
           });
           loaders.push(fetcher);
-          //Load tezApp details
-          if (dag.get('status') === 'RUNNING') {
-            App.Helpers.misc.removeRecord(store, 'dagProgress', dag.get('id'));
-            amInfoFetcher = store.find('dagProgress', dag.get('id'), {
-              appId: dag.get('applicationId'),
-              dagIdx: dag.get('idx')
-            })
-            .then(function(dagProgressInfo) {
-              dag.set('progress', dagProgressInfo.get('progress'));
-            })
-            .catch(function(error) {
-              Em.Logger.error('Failed to fetch dagProgress' + error);
-            });
-            loaders.push(amInfoFetcher);
-          }
         }
-      });
-      Em.RSVP.allSettled(loaders).then(function(){
-        that.set('entities', entities);
-        that.set('loading', false);
-      });
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
+      }
+
     });
-  },
 
-  actions : {
-    filterUpdated: function(filterID, value) {
-      // any validations required goes here.
-      if (!!value) {
-        this.set(filterID, value);
-      } else {
-        this.set(filterID, null);
-      }
-      this.loadData();
-    }
+    return Em.RSVP.allSettled(loaders);
   },
 
   defaultColumnConfigs: function() {
+    var store = this.get('store');
     return [
       {
         id: 'dagName',
         headerCellName: 'Dag Name',
         filterID: 'dagName_filter',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'dag' view.cellContent.id class='ember-table-content'}}{{view.cellContent.name}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'name',
         getCellContent: function(row) {
           return {
-            id: row.get('id'),
-            name: row.get('name')
+            linkTo: 'dag',
+            entityId: row.get('id'),
+            displayText: row.get('name')
           };
         }
       },
@@ -150,59 +83,70 @@ App.TezAppDagsController = Em.ObjectController.extend(App.PaginatedContentMixin,
       {
         id: 'user',
         headerCellName: 'Submitter',
-        filterID: 'user_filter',
         contentPath: 'user'
       },
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.dagStatusUIOptions,
-        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}}\
-            {{#if view.cellContent.progress}} {{bs-badge content=view.cellContent.progress}}{{/if}}</span>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
-          var pct;
-          if (Ember.typeOf(row.get('progress')) === 'number') {
-            pct = App.Helpers.number.fractionToPercentage(row.get('progress'));
+          var status = row.get('status'),
+              content = Ember.Object.create({
+                status: status,
+                statusIcon: App.Helpers.misc.getStatusClassForEntity(status)
+              });
+
+          if(status == 'RUNNING') {
+            App.Helpers.misc.removeRecord(store, 'dagProgress', row.get('id'));
+
+            store.find('dagProgress', row.get('id'), {
+              appId: row.get('applicationId'),
+              dagIdx: row.get('idx')
+            })
+            .then(function(dagProgressInfo) {
+              content.set('progress', dagProgressInfo.get('progress'));
+            })
+            .catch(function(error) {
+              Em.Logger.error('Failed to fetch dagProgress' + error);
+            });
           }
-          var dagStatus = row.get('status');
-          return {
-            status: dagStatus,
-            statusIcon: App.Helpers.misc.getStatusClassForEntity(dagStatus),
-            progress: pct
-          };
+
+          return content;
         }
       },
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
         }
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
-        }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
       }
     ];
   }.property(),

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/vertex-additionals-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex-additionals-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex-additionals-controller.js
index 61c2616..43f3653 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex-additionals-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex-additionals-controller.js
@@ -35,71 +35,70 @@ App.VertexAdditionalsController = Em.ObjectController.extend({
   },
 
   inputColumns: function() {
-    return App.Helpers.misc.createColumnsFromConfigs([
+    return App.Helpers.misc.createColumnDescription([
       {
         id: 'inputId',
         headerCellName: 'Name',
         contentPath: 'inputName',
+        searchAndSortable: false,
       },
       {
         id: 'inputClass',
         headerCellName: 'Class',
         contentPath: 'inputClass',
+        searchAndSortable: false,
       },
       {
         id: 'inputInitializer',
         headerCellName: 'Initializer',
         contentPath: 'inputInitializer',
+        searchAndSortable: false,
       },
       {
         id: 'configurations',
         headerCellName: 'Configurations',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#if view.cellContent.count}}\
-              {{#link-to 'input.configs' view.cellContent.id class='ember-table-content'}}View Configurations{{/link-to}}\
-            {{else}}\
-              <span class='ember-table-content'>Not Available</span>\
-            {{/if}}")
-        }),
+        searchAndSortable: false,
+        templateName: 'components/basic-table/linked-cell',
         getCellContent: function(row) {
-          return {
-            count: row.get('configs.content.length'),
-            id: row.get('id')
-          };
+          if(row.get('configs.content.length')) {
+            return {
+              linkTo: 'input.configs',
+              displayText: 'View Configurations',
+              entityId: row.get('id')
+            };
+          }
         }
       }
     ]);
   }.property(),
 
   outputColumns: function() {
-    return App.Helpers.misc.createColumnsFromConfigs([
+    return App.Helpers.misc.createColumnDescription([
       {
         id: 'outputId',
         headerCellName: 'Name',
         contentPath: 'outputName',
+        searchAndSortable: false,
       },
       {
         id: 'outputClass',
         headerCellName: 'Class',
         contentPath: 'outputClass',
+        searchAndSortable: false,
       },
       {
         id: 'configurations',
         headerCellName: 'Configurations',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#if view.cellContent.count}}\
-              {{#link-to 'output.configs' view.cellContent.id class='ember-table-content'}}View Configurations{{/link-to}}\
-            {{else}}\
-              <span class='ember-table-content'>Not Available</span>\
-            {{/if}}")
-        }),
+        searchAndSortable: false,
+        templateName: 'components/basic-table/linked-cell',
         getCellContent: function(row) {
-          return {
-            count: row.get('configs.content.length'),
-            id: row.get('id')
-          };
+          if(row.get('configs.content.length')) {
+            return {
+              linkTo: 'output.configs',
+              displayText: 'View Configurations',
+              entityId: row.get('id')
+            };
+          }
         }
       }
     ]);

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
index c335615..1bebd53 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_task_attempts_controller.js
@@ -16,82 +16,41 @@
  * limitations under the License.
  */
 
-App.VertexTaskAttemptsController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  // Required by the PaginatedContentMixin
-  childEntityType: 'taskAttempt',
+App.VertexTaskAttemptsController = App.TablePageController.extend({
 
   controllerName: 'VertexTaskAttemptsController',
+  needs: "vertex",
 
-  needs: 'vertex',
+  entityType: 'taskAttempt',
+  filterEntityType: 'vertex',
+  filterEntityId: Ember.computed.alias('controllers.vertex.id'),
 
-  queryParams: {
-    status_filter: 'status',
+  beforeLoad: function () {
+    var controller = this.get('controllers.vertex'),
+        model = controller.get('model');
+    return model.reload().then(function () {
+      return controller.loadAdditional(model);
+    });
   },
-  status_filter: null,
 
-  loadData: function() {
-    var filters = {
-      primary: {
-        TEZ_VERTEX_ID: this.get('controllers.vertex.id')
-      },
-      secondary: {
-        status: this.status_filter
+  afterLoading: function () {
+    var data = this.get('data'),
+        isUnsuccessfulVertex = App.Helpers.misc.isStatusInUnsuccessful(
+          that.get('controllers.vertex.status')
+        );
+
+    data.forEach(function (attempt) {
+      var attemptStatus = App.Helpers.misc
+        .getFixedupDisplayStatus(attempt.get('status'));
+      if (attemptStatus == 'RUNNING' && isUnsuccessfulVertex) {
+        attemptStatus = 'KILLED'
       }
-    }
-    this.setFiltersAndLoadEntities(filters);
-  },
-
-  load: function () {
-    var vertex = this.get('controllers.vertex.model'),
-        controller = this.get('controllers.vertex'),
-        t = this;
-    vertex.reload().then(function () {
-      return controller.loadAdditional(vertex);
-    }).then(function () {
-      t.resetNavigation();
-      t.loadEntities();
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
-    });
-  }.observes('count'),
-
-  actions : {
-    filterUpdated: function(filterID, value) {
-      // any validations required goes here.
-      if (!!value) {
-        this.set(filterID, value);
-      } else {
-        this.set(filterID, null);
+      if (attemptStatus != attempt.get('status')) {
+        attempt.set('status', attemptStatus);
       }
-      this.loadData();
-    }
-  },
-
-  updateLoading: function () {
-    var controller = this.get('controllers.vertex'),
-        model = this.get('controllers.vertex.model'),
-        that = this,
-        vertexStatus = that.get('controllers.vertex.status');
-
-    controller.loadAdditional(model).then(function () {
-      that.get('entities').forEach(function (attempt) {
-
-        var attemptStatus = App.Helpers.misc
-          .getFixedupDisplayStatus(attempt.get('status'));
-        if (attemptStatus == 'RUNNING' &&
-          App.Helpers.misc.isStatusInUnsuccessful(vertexStatus)) {
-          attemptStatus = 'KILLED'
-        }
-        if (attemptStatus != attempt.get('status')) {
-          attempt.set('status', attemptStatus);
-        }
-      });
-
-      that.set('loading', false);
     });
+
+    return this._super();
   },
 
   defaultColumnConfigs: function() {
@@ -100,74 +59,81 @@ App.VertexTaskAttemptsController = Em.ObjectController.extend(App.PaginatedConte
       {
         id: 'taskId',
         headerCellName: 'Task Index',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'task' view.cellContent.taskId class='ember-table-content'}}{{view.cellContent.displayId}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'taskID',
         getCellContent: function (row) {
           var taskId = row.get('taskID'),
               idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
           return {
-            taskId: taskId,
-            displayId: taskId.indexOf(idPrefix) == 0 ? taskId.substr(idPrefix.length) : taskId
+            linkTo: 'task',
+            entityId: taskId,
+            displayText: taskId.indexOf(idPrefix) == 0 ? taskId.substr(idPrefix.length) : taskId
           };
+        },
+        getSearchValue: function (row) {
+          var id = row.get('taskID'),
+              idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
+          return id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id;
         }
       },
       {
         id: 'attemptNo',
         headerCellName: 'Attempt No',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'taskAttempt' view.cellContent.attemptID class='ember-table-content'}}{{view.cellContent.attemptNo}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'id',
         getCellContent: function(row) {
-          var attemptID = row.get('id') || '',
-              attemptNo = attemptID.split(/[_]+/).pop();
+          var attemptID = row.get('id') || '';
           return {
-            attemptNo: attemptNo,
-            attemptID: attemptID
+            linkTo: 'taskAttempt',
+            displayText: attemptID.split(/[_]+/).pop(),
+            entityId: attemptID
           };
+        },
+        getSearchValue: function (row) {
+          var attemptID = row.get('id') || '';
+          return attemptID.split(/[_]+/).pop();
         }
       },
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
-        }
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
-        }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
       },
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.taskAttemptStatusUIOptions,
-        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>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
-          var status = row.get('status');
+          var status = App.Helpers.misc.getFixedupDisplayStatus(row.get('status'));
           return {
             status: status,
             statusIcon: App.Helpers.misc.getStatusClassForEntity(status)
@@ -187,34 +153,23 @@ App.VertexTaskAttemptsController = Em.ObjectController.extend(App.PaginatedConte
       {
         id: 'actions',
         headerCellName: 'Actions',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-            {{#link-to "taskAttempt.counters" view.cellContent}}counters{{/link-to}}&nbsp;\
-            </span>'
-            )
-        }),
-        contentPath: 'id'
+        templateName: 'components/basic-table/linked-cell',
+        searchAndSortable: false,
+        contentPath: 'id',
+        getCellContent: function(row) {
+          var attemptID = row.get('id') || '';
+          return {
+            linkTo: 'taskAttempt.counters',
+            displayText: 'counters',
+            entityId: attemptID
+          };
+        }
       },
       {
         id: 'logs',
         headerCellName: 'Logs',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-              {{#unless view.cellContent.notAvailable}}\
-                Not Available\
-              {{else}}\
-                {{#if view.cellContent.viewUrl}}\
-                  <a target="_blank" href="//{{unbound view.cellContent.viewUrl}}">View</a>\
-                  &nbsp;\
-                {{/if}}\
-                {{#if view.cellContent.downloadUrl}}\
-                  <a target="_blank" href="{{unbound view.cellContent.downloadUrl}}?start=0" download type="application/octet-stream">Download</a>\
-                {{/if}}\
-              {{/unless}}\
-            </span>')
-        }),
+        templateName: 'components/basic-table/logs-cell',
+        searchAndSortable: false,
         getCellContent: function(row) {
           var yarnAppState = that.get('controllers.vertex.yarnAppState'),
               suffix = "/syslog_" + row.get('id'),

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
index 912064a..8b815b0 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_tasks_controller.js
@@ -16,161 +16,129 @@
  * limitations under the License.
  */
 
-App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, App.ColumnSelectorMixin, {
-  // Required by the PaginatedContentMixin
-  childEntityType: 'task',
+App.VertexTasksController = App.TablePageController.extend({
 
   controllerName: 'VertexTasksController',
+  needs: "vertex",
 
-  needs: 'vertex',
+  entityType: 'task',
+  filterEntityType: 'vertex',
+  filterEntityId: Ember.computed.alias('controllers.vertex.id'),
 
-  queryParams: {
-    status_filter: 'status',
+  beforeLoad: function () {
+    var controller = this.get('controllers.vertex'),
+        model = controller.get('model');
+    return model.reload().then(function () {
+      return controller.loadAdditional(model);
+    });
   },
-  status_filter: null,
 
-  loadData: function() {
-    var filters = {
-      primary: {
-        TEZ_VERTEX_ID: this.get('controllers.vertex.id')
-      },
-      secondary: {
-        status: this.status_filter
+  afterLoad: function () {
+    var data = this.get('data'),
+        isUnsuccessfulVertex = App.Helpers.misc.isStatusInUnsuccessful(
+          this.get('controllers.vertex.status')
+        );
+
+    data.forEach(function (task) {
+      var taskStatus = App.Helpers.misc.getFixedupDisplayStatus(task.get('status'));
+
+      if (taskStatus == 'RUNNING' && isUnsuccessfulVertex) {
+        taskStatus = 'KILLED'
       }
-    }
-    this.setFiltersAndLoadEntities(filters);
+      if (taskStatus != task.get('status')) {
+        task.set('status', taskStatus);
+      }
+    });
+
+    return this._super();
   },
 
-  load: function () {
-    var vertex = this.get('controllers.vertex.model'),
-        controller = this.get('controllers.vertex'),
-        t = this;
-    vertex.reload().then(function () {
-      return controller.loadAdditional(vertex);
-    }).then(function () {
-      t.resetNavigation();
-      t.loadEntities();
-    }).catch(function(error){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
-    });
-  }.observes('count'),
-
-  loadEntities: function() {
-    var that = this,
-    store = this.get('store'),
-    fetcher;
-    childEntityType = this.get('childEntityType');
-    var defaultErrMsg = 'Error while loading tasks.';
-
-    that.set('loading', true);
-    store.unloadAll(childEntityType);
-    store.findQuery(childEntityType, this.getFilterProperties()).then(function(entities){
-      var pivotLoaders = [],
-          vertexStatus = that.get('controllers.vertex.status');
-      entities.forEach(function (task) {
-        var taskStatus = App.Helpers.misc
-          .getFixedupDisplayStatus(task.get('status'));
-        if (taskStatus == 'RUNNING' &&
-          App.Helpers.misc.isStatusInUnsuccessful(vertexStatus)) {
-          taskStatus = 'KILLED';
-        }
-        if (taskStatus != task.get('status')) {
-          task.set('status', taskStatus);
+  defaultColumnConfigs: function() {
+    var that = this;
+
+    function getLogContent(attempt) {
+      var yarnAppState = that.get('controllers.vertex.yarnAppState'),
+          suffix,
+          link,
+          cellContent = {};
+
+      if(attempt) {
+        suffix = "/syslog_" + attempt.get('id'),
+        link = attempt.get('inProgressLog') || attempt.get('completedLog');
+
+        if(link) {
+          cellContent.viewUrl = link + suffix;
         }
-        var taskAttemptId = task.get('successfulAttemptId') || task.get('attempts.lastObject');
-        if (!!taskAttemptId) {
-          // Pivot attempt selection logic
-          App.Helpers.misc.removeRecord(store, 'taskAttempt', taskAttemptId);
-          fetcher = store.find('taskAttempt', taskAttemptId);
-          fetcher.then(function (attempt) {
-            task.set('pivotAttempt', attempt);
-          });
-          pivotLoaders.push(fetcher);
+        link = attempt.get('completedLog');
+        if (link && yarnAppState === 'FINISHED' || yarnAppState === 'KILLED' || yarnAppState === 'FAILED') {
+          cellContent.downloadUrl = link + suffix;
         }
-      });
-      Em.RSVP.allSettled(pivotLoaders).then(function(){
-        that.set('entities', entities);
-        that.set('loading', false);
-      });
-    }).catch(function(jqXHR){
-      Em.Logger.error(error);
-      var err = App.Helpers.misc.formatError(error, defaultErrMsg);
-      var msg = 'error code: %@, message: %@'.fmt(err.errCode, err.msg);
-      App.Helpers.ErrorBar.getInstance().show(msg, err.details);
-    });
-  },
-
-  actions : {
-    filterUpdated: function(filterID, value) {
-      // any validations required goes here.
-      if (!!value) {
-        this.set(filterID, value);
-      } else {
-        this.set(filterID, null);
       }
-      this.loadData();
+
+      cellContent.notAvailable = cellContent.viewUrl || cellContent.downloadUrl;
+
+      return cellContent;
     }
-  },
 
-  defaultColumnConfigs: function() {
-    var that = this;
     return [
       {
         id: 'id',
         headerCellName: 'Task Index',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            "{{#link-to 'task' view.cellContent.id class='ember-table-content'}}{{view.cellContent.displayId}}{{/link-to}}")
-        }),
+        templateName: 'components/basic-table/linked-cell',
+        contentPath: 'id',
         getCellContent: function (row) {
           var id = row.get('id'),
               idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
           return {
-            id: id,
-            displayId: id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id
+            linkTo: 'task',
+            entityId: id,
+            displayText: id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id
           };
+        },
+        getSearchValue: function (row) {
+          var id = row.get('id'),
+              idPrefix = 'task_%@_'.fmt(row.get('dagID').substr(4));
+          return id.indexOf(idPrefix) == 0 ? id.substr(idPrefix.length) : id;
         }
       },
       {
         id: 'startTime',
         headerCellName: 'Start Time',
+        contentPath: 'startTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('startTime'));
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('startTime'));
         }
       },
       {
         id: 'endTime',
         headerCellName: 'End Time',
+        contentPath: 'endTime',
         getCellContent: function(row) {
           return App.Helpers.date.dateFormat(row.get('endTime'));
-        }
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.dateFormat(row.get('endTime'));
+        },
       },
       {
         id: 'duration',
         headerCellName: 'Duration',
+        contentPath: 'duration',
         getCellContent: function(row) {
-          var st = row.get('startTime');
-          var et = row.get('endTime');
-          if (st && et) {
-            return App.Helpers.date.durationSummary(st, et);
-          }
-        }
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
+        getSearchValue: function(row) {
+          return App.Helpers.date.timingFormat(row.get('duration'), 1);
+        },
       },
       {
         id: 'status',
         headerCellName: 'Status',
-        filterID: 'status_filter',
-        filterType: 'dropdown',
-        dropdownValues: App.Helpers.misc.taskStatusUIOptions,
-        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>')
-        }),
+        templateName: 'components/basic-table/status-cell',
+        contentPath: 'status',
         getCellContent: function(row) {
           var status = row.get('status');
           return {
@@ -182,62 +150,25 @@ App.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin
       {
         id: 'actions',
         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'
+        templateName: 'components/basic-table/task-actions-cell',
+        contentPath: 'id',
+        searchAndSortable: false
       },
       {
         id: 'logs',
         headerCellName: 'Logs',
-        tableCellViewClass: Em.Table.TableCell.extend({
-          template: Em.Handlebars.compile(
-            '<span class="ember-table-content">\
-              {{#unless view.cellContent.notAvailable}}\
-                Not Available\
-              {{else}}\
-                {{#if view.cellContent.viewUrl}}\
-                  <a target="_blank" href="//{{unbound view.cellContent.viewUrl}}">View</a>\
-                  &nbsp;\
-                {{/if}}\
-                {{#if view.cellContent.downloadUrl}}\
-                  <a target="_blank" href="{{unbound view.cellContent.downloadUrl}}?start=0" download type="application/octet-stream">Download</a>\
-                {{/if}}\
-              {{/unless}}\
-            </span>')
-        }),
+        templateName: 'components/basic-table/logs-cell',
+        searchAndSortable: false,
         getCellContent: function(row) {
-          var yarnAppState = that.get('controllers.vertex.yarnAppState'),
-              attempt = row.get('pivotAttempt'),
-              suffix,
-              link,
-              cellContent = {};
-
-          if(attempt) {
-            suffix = "/syslog_" + attempt.get('id'),
-            link = attempt.get('inProgressLog') || attempt.get('completedLog');
-
-            if(link) {
-              cellContent.viewUrl = link + suffix;
-            }
-            link = attempt.get('completedLog');
-            if (link && yarnAppState === 'FINISHED' || yarnAppState === 'KILLED' || yarnAppState === 'FAILED') {
-              cellContent.downloadUrl = link + suffix;
-            }
-          }
-
-          cellContent.notAvailable = cellContent.viewUrl || cellContent.downloadUrl;
+          var taskAttemptId = row.get('successfulAttemptId') || row.get('attempts.lastObject'),
+              store = that.get('store');
 
-          return cellContent;
+          if (taskAttemptId) {
+            return store.find('taskAttempt', taskAttemptId).then(getLogContent);
+          }
         }
       }
     ];
-
   }.property(),
 
   columnConfigs: function() {

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/mixins/column-selector-mixin.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/mixins/column-selector-mixin.js b/tez-ui/src/main/webapp/app/scripts/mixins/column-selector-mixin.js
index 12b86c9..d3b3bbd 100644
--- a/tez-ui/src/main/webapp/app/scripts/mixins/column-selector-mixin.js
+++ b/tez-ui/src/main/webapp/app/scripts/mixins/column-selector-mixin.js
@@ -37,6 +37,7 @@ App.ColumnSelectorMixin = Em.Mixin.create({
 
   _storeKey: '',
   visibleColumnIds: {},
+  columnConfigs: [],
 
   columnSelectorTitle: 'Column Selector',
 
@@ -65,7 +66,7 @@ App.ColumnSelectorMixin = Em.Mixin.create({
       return this.visibleColumnIds[column.id];
     }, this);
 
-    return App.Helpers.misc.createColumnsFromConfigs(visibleColumnConfigs);
+    return App.Helpers.misc.createColumnDescription(visibleColumnConfigs);
   }.property('visibleColumnIds'),
 
   actions: {

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/router.js b/tez-ui/src/main/webapp/app/scripts/router.js
index 6de5a5d..29ac3cc 100644
--- a/tez-ui/src/main/webapp/app/scripts/router.js
+++ b/tez-ui/src/main/webapp/app/scripts/router.js
@@ -74,6 +74,10 @@ function renderConfigs() {
   this.render('common/configs');
 }
 
+function renderTable() {
+  this.render('common/table');
+}
+
 /*
  * Creates a setupController function
  * @param format Unformatted title string.
@@ -175,12 +179,6 @@ App.TaskRoute = Em.Route.extend({
 });
 
 App.TasksRoute = Em.Route.extend({
-  queryParams: {
-    count: App.Helpers.misc.defaultQueryParamsConfig,
-    status: App.Helpers.misc.defaultQueryParamsConfig,
-    parentType: App.Helpers.misc.defaultQueryParamsConfig,
-    parentID: App.Helpers.misc.defaultQueryParamsConfig
-  },
   setupController: setupControllerFactory()
 });
 
@@ -243,11 +241,7 @@ App.TaskAttemptRoute = Em.Route.extend({
 });
 
 App.TaskAttemptsRoute = Em.Route.extend({
-  renderTemplate: renderTableWithSpinner,
-  queryParams: {
-    count: App.Helpers.misc.defaultQueryParamsConfig,
-    status: App.Helpers.misc.defaultQueryParamsConfig 
-  },
+  renderTemplate: renderTable,
   setupController: setupControllerFactory('Task Attempt: %@', 'id')
 });
 
@@ -268,14 +262,7 @@ App.TezAppRoute = Em.Route.extend({
 });
 
 App.TezAppDagsRoute = Em.Route.extend({
-  renderTemplate: renderTableWithSpinner,
-  queryParams:  {
-    dagName: App.Helpers.misc.defaultQueryParamsConfig,
-    count: App.Helpers.misc.defaultQueryParamsConfig,
-    fromID: App.Helpers.misc.defaultQueryParamsConfig,
-    user: App.Helpers.misc.defaultQueryParamsConfig,
-    status: App.Helpers.misc.defaultQueryParamsConfig
-  },
+  renderTemplate: renderTable,
   setupController: setupControllerFactory()
 });
 
@@ -285,28 +272,13 @@ App.TezAppConfigsRoute = Em.Route.extend({
 
 /* --- Shared routes --- */
 
-App.DagTasksRoute = Em.Route.extend({
-  renderTemplate: function () {
-    this.render('common/table');
-  },
-  setupController: function (controller, model) {
-    this._super(controller, model);
-    if(controller.loadData) {
-      controller.loadData();
-    }
-  }
-});
-
-App.DagVerticesRoute =
+App.DagTasksRoute =
+    App.DagVerticesRoute =
     App.DagTaskAttemptsRoute =
     App.VertexTasksRoute =
     App.VertexTaskAttemptsRoute =
     Em.Route.extend({
-      renderTemplate: renderTableWithSpinner,
-      queryParams: {
-        count: App.Helpers.misc.defaultQueryParamsConfig,
-        status: App.Helpers.misc.defaultQueryParamsConfig
-      },
+      renderTemplate: renderTable,
       setupController: setupControllerFactory()
     });
 

http://git-wip-us.apache.org/repos/asf/tez/blob/f3828283/tez-ui/src/main/webapp/app/templates/components/basic-table/vertex-configurations-cell.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/components/basic-table/vertex-configurations-cell.hbs b/tez-ui/src/main/webapp/app/templates/components/basic-table/vertex-configurations-cell.hbs
new file mode 100644
index 0000000..17fb7e3
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/components/basic-table/vertex-configurations-cell.hbs
@@ -0,0 +1,31 @@
+{{!
+* 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.
+}}
+
+{{#if view.cellContent._notAvailable}}
+  {{view.cellContent}}
+{{else}}
+  {{#if view.cellContent.linkToAdditionals}}
+      {{#link-to 'vertex.additionals' view.cellContent.vertexId class='ember-table-content'}}View sources & sinks{{/link-to}}
+  {{else}}{{#if view.cellContent.inputId}}
+    {{#link-to 'input.configs' view.cellContent.vertexId view.cellContent.inputId class='ember-table-content'}}View source configs{{/link-to}}
+  {{else}}{{#if view.cellContent.outputId}}
+    {{#link-to 'output.configs' view.cellContent.vertexId view.cellContent.outputId class='ember-table-content'}}View sink configs{{/link-to}}
+  {{else}}
+    <span class='ember-table-content'>No source or sink</span>
+  {{/if}}{{/if}}{{/if}}
+{{/if}}
\ No newline at end of file


Mime
View raw message