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

[35/53] tez git commit: TEZ-1781. Configurations view ~ New design (Sreenath Somarajapuram via Rajesh Balamohan)

TEZ-1781. Configurations view ~ New design (Sreenath Somarajapuram via Rajesh Balamohan)


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

Branch: refs/heads/master
Commit: 7f8198f118750a9a02845aee7b1ea908a83dd4ed
Parents: 052f71c
Author: Rajesh Balamohan <rb...@hortonworks.com>
Authored: Wed Nov 19 10:50:45 2014 +0530
Committer: Rajesh Balamohan <rb...@hortonworks.com>
Committed: Wed Nov 19 10:50:45 2014 +0530

----------------------------------------------------------------------
 tez-ui/src/main/webapp/app/scripts/app.js       | 39 +++++++++
 .../webapp/app/scripts/components/kv-table.js   | 42 ++++++++++
 .../app/scripts/controllers/dag_vertices.js     | 29 ++++++-
 .../app/scripts/controllers/dags_controller.js  | 35 ++++++--
 .../controllers/tez-app-configs-controller.js   | 88 --------------------
 .../scripts/controllers/tez-app-controller.js   |  2 +-
 .../controllers/vertex-inputs-controller.js     | 77 +++++++++++++++++
 .../scripts/controllers/vertex_controller.js    |  1 +
 .../app/scripts/mixins/paginated_content.js     |  1 +
 .../app/scripts/models/TimelineRestAdapter.js   | 63 +++++++++++++-
 .../src/main/webapp/app/scripts/models/dag.js   | 24 +++++-
 tez-ui/src/main/webapp/app/scripts/router.js    | 40 ++++++---
 tez-ui/src/main/webapp/app/styles/main.less     | 25 +++++-
 .../webapp/app/templates/common/configs.hbs     | 21 +++++
 .../app/templates/components/kv-table.hbs       | 39 +++++++++
 .../webapp/app/templates/tez-app/configs.hbs    | 46 ----------
 .../main/webapp/app/templates/vertex/inputs.hbs | 49 +++++++++++
 17 files changed, 457 insertions(+), 164 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/app.js b/tez-ui/src/main/webapp/app/scripts/app.js
index c08c21f..91f0e7a 100644
--- a/tez-ui/src/main/webapp/app/scripts/app.js
+++ b/tez-ui/src/main/webapp/app/scripts/app.js
@@ -53,6 +53,45 @@ Ember.Application.initializer({
       },
     });
 
+    application.VertexAdapter = App.ApplicationAdapter.extend({
+      _setInputs: function (store, data) {
+        var dagId = Ember.get(data, 'primaryfilters.TEZ_DAG_ID.0'),
+            vertexName = Ember.get(data, 'otherinfo.vertexName');
+        if(dagId) {
+          return store.find('dag', dagId).then(function (dag) {
+            if(dag.get('vertices') instanceof Array) {
+              var vertexData = dag.get('vertices').findBy('vertexName', vertexName);
+              if(vertexData && vertexData.additionalInputs) {
+                data.inputs = vertexData.additionalInputs;
+              }
+            }
+            return data;
+          });
+        }
+        else {
+          return Em.RSVP.Promise(data);
+        }
+      },
+      find: function(store, type, id) {
+        var that = this;
+        return this._super(store, type, id).then(function (data) {
+          return that._setInputs(store, data);
+        });
+      },
+      findQuery: function(store, type, queryObj, records) {
+        var that = this;
+        return that._super(store, type, queryObj, records ).then(function (data) {
+          var fetchers = [];
+          data.entities.forEach(function (datum) {
+            fetchers.push(that._setInputs(store, datum));
+          });
+          return Em.RSVP.allSettled(fetchers).then(function () {
+            return data;
+          });
+        });
+      }
+    });
+
   }
 });
 

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/components/kv-table.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/components/kv-table.js b/tez-ui/src/main/webapp/app/scripts/components/kv-table.js
new file mode 100644
index 0000000..02beeea
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/components/kv-table.js
@@ -0,0 +1,42 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.KvTableComponent = Em.Component.extend({
+  layoutName: 'components/kv-table',
+  filterExp: null,
+
+  filteredKVs: function() {
+    var kvList = this.get('data') || [],
+        filteredKvs = [],
+        filterStringRegex = new RegExp(this.filterExp, 'i');
+
+    if (Em.isEmpty(this.filterExp)) {
+      return kvList;
+    }
+
+    kvList.forEach(function (kv) {
+      if (filterStringRegex.test(kv.get('key')) || filterStringRegex.test(kv.get('value'))) {
+        filteredKvs.push(kv);
+      }
+    });
+
+    return filteredKvs;
+  }.property('data', 'filterExp')
+});
+
+Em.Handlebars.helper('kv-table-component', App.KvTableComponent);

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/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 f1d6347..947d717 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
@@ -110,13 +110,36 @@ App.DagVerticesController = Em.ObjectController.extend(App.PaginatedContentMixin
           &nbsp;&nbsp;{{view.cellContent.status}}</span>')
       }),
       getCellContent: function(row) {
-      	return { 
+        return {
           status: row.get('status'),
           statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
         };
       }
     });
 
-		return [idCol, nameCol, startTimeCol, endTimeCol, firstTaskStartTime, statusCol, numTasksCol];
-	}.property(),
+    var configsCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Input Configurations',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          " {{#if view.cellContent.inputId}}\
+              {{#if view.cellContent.showConfigs}}\
+               {{#link-to 'vertexInput.configs' view.cellContent.vertexId view.cellContent.inputId class='ember-table-content'}}View configurations{{/link-to}}\
+              {{else}}\
+               {{#link-to 'vertex.inputs' view.cellContent.vertexId class='ember-table-content'}}View Inputs{{/link-to}}\
+              {{/if}}\
+            {{else}}\
+              <span class='ember-table-content'>No Inputs</span>\
+            {{/if}}")
+      }),
+      getCellContent: function(row) {
+        return {
+          showConfigs: row.get('inputs.content.length') == 1 && row.get('inputs.content.0.configs.length') > 0,
+          inputId: row.get('inputs.content.0.id'),
+          vertexId: row.get('id')
+        };
+      }
+    });
+
+    return [idCol, nameCol, startTimeCol, endTimeCol, firstTaskStartTime, statusCol, numTasksCol, configsCol];
+  }.property(),
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/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 cdc65ff..ee92a33 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
@@ -80,17 +80,27 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
       var loaders = [];
       that.set('entities', entities);
       entities.forEach(function (dag) {
-        // Pivot attempt selection logic
-        fetcher = store.find('appDetail', dag.get('applicationId') );
-        fetcher.then(function (app) {
-          dag.set('app', app);
-        });
-        loaders.push(fetcher);
+        var appId = dag.get('applicationId');
+        if(appId) {
+          // Pivot attempt selection logic
+          fetcher = store.find('appDetail', appId);
+          fetcher.then(function (app) {
+            dag.set('appDetail', app);
+          });
+          loaders.push(fetcher);
+          //Load tezApp details
+          fetcher = store.find('tezApp', 'tez_' + appId);
+          fetcher.then(function (app) {
+            dag.set('tezApp', app);
+          });
+          loaders.push(fetcher);
+        }
       });
       Em.RSVP.allSettled(loaders).then(function(){
         that.set('loading', false);
       });
     }).catch(function(jqXHR){
+      if(console) console.log(jqXHR);
       alert('failed');
     });
   },
@@ -194,17 +204,24 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
       filterID: 'appId_filter',
       tableCellViewClass: Em.Table.TableCell.extend({
         template: Em.Handlebars.compile(
-          "{{#link-to 'tez-app' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+          "{{#if view.cellContent.enableLink}}\
+             {{#link-to 'tez-app' view.cellContent.appId class='ember-table-content'}}{{view.cellContent.appId}}{{/link-to}}\
+           {{else}}\
+             <span class='ember-table-content'>{{view.cellContent.appId}}</span>\
+           {{/if}}")
       }),
       getCellContent: function(row) {
-        return  row.get('applicationId')
+        return  {
+          enableLink: row.get('tezApp'),
+          appId: row.get('applicationId')
+        }
       }
     });
     var queue = App.ExTable.ColumnDefinition.create({
       textAlign: 'text-align-left',
       headerCellName: 'Queue',
       getCellContent: function(row) {
-        return (row.get('app') && row.get('app').get('queue')) || 'Not Available';
+        return row.get('appDetail.queue') || 'Not Available';
       }
     });
     return [nameCol, idCol, userCol, statusCol, startTime, endTime, durationCol, appIdCol, queue];

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
deleted file mode 100644
index a50f589..0000000
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
+++ /dev/null
@@ -1,88 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-App.TezAppConfigsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
-  needs: "tezApp",
-  count: 10,
-
-  key: null,
-  value: null,
-
-  loadEntities: function() {
-    count = 0,
-    filter = this.getFilterProperties(),
-    configs = this.get('configs').content,
-    filtered = [],
-    i = 0;
-
-    if(filter.fromId) {
-      while(i < configs.length && configs[i].id != filter.fromId) {
-        i++;
-      }
-    }
-
-    // Filter the available data
-    for(; i < configs.length && filtered.length < filter.limit; i++){
-      if((this.key === null || configs[i].get('key').indexOf(this.key) !=-1) && (this.value === null || configs[i].get('value').indexOf(this.value) != -1)) {
-        filtered.push(configs[i]);
-      }
-    }
-
-    this.set('entities', filtered);
-    this.set('loading', false);
-  },
-
-  loadData: function() {
-    var filters = {
-      primary: {
-        key: this.key,
-        value: this.value
-      },
-    };
-    this.setFiltersAndLoadEntities(filters);
-  },
-
-  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 columnHelper = function(displayText, columnId) {
-      return App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin, {
-        textAlign: 'text-align-left',
-        headerCellName: displayText,
-        filterID: columnId,
-        contentPath: columnId
-      });
-    }
-
-    return [
-        columnHelper("Conf key", 'key'),
-        columnHelper("Conf value", 'value'),
-    ];
-  }.property(),
-
-});

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
index 74e985c..d7312ef 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
@@ -36,6 +36,6 @@ App.TezAppController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
   childDisplayViews: [
     Ember.Object.create({title: 'Details', linkTo: 'tez-app.index'}),
     Ember.Object.create({title: 'Dags', linkTo: 'tez-app.dags'}),
-    Ember.Object.create({title: 'Configs', linkTo: 'tez-app.configs'}),
+    Ember.Object.create({title: 'Configuration', linkTo: 'tez-app.configs'}),
   ],
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/controllers/vertex-inputs-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex-inputs-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex-inputs-controller.js
new file mode 100644
index 0000000..d08949e
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex-inputs-controller.js
@@ -0,0 +1,77 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.VertexInputsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+  needs: 'vertex',
+
+  loadEntities: function() {
+    var content = this.get('inputs').content;
+    this.set('entities', content);
+    this.set('inputsAvailable', content.length > 0);
+    this.set('loading', false);
+  },
+
+  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 nameCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Name',
+      contentPath: 'inputName',
+    });
+
+    var classCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Class',
+      contentPath: 'inputClass',
+    });
+
+    var initializerCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Initializer',
+      contentPath: 'inputInitializer',
+    });
+
+    var configCol = App.ExTable.ColumnDefinition.create({
+      headerCellName: 'Configurations',
+      tableCellViewClass: Em.Table.TableCell.extend({
+        template: Em.Handlebars.compile(
+          "{{#if view.cellContent.count}}\
+            {{#link-to 'vertexInput.configs' view.cellContent.id class='ember-table-content'}}View Configurations{{/link-to}}\
+          {{else}}\
+            <span class='ember-table-content'>Not Available</span>\
+          {{/if}}")
+      }),
+      getCellContent: function(row) {
+        return {
+          count: row.get('configs.content.length'),
+          id: row.get('id')
+        };
+      }
+    });
+
+    return [nameCol, classCol, initializerCol, configCol];
+  }.property(),
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
index 905d8d3..51bd1dc 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/vertex_controller.js
@@ -36,5 +36,6 @@ App.VertexController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
     Ember.Object.create({title: 'Tasks', linkTo: 'vertex.tasks'}),
     Ember.Object.create({title: 'Counters', linkTo: 'vertex.counters'}),
     Ember.Object.create({title: 'Swimlane', linkTo: 'vertex.swimlane'}),
+    Ember.Object.create({title: 'Inputs', linkTo: 'vertex.inputs'}),
   ],
 });
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js b/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
index b650705..0dbf097 100644
--- a/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
+++ b/tez-ui/src/main/webapp/app/scripts/mixins/paginated_content.js
@@ -53,6 +53,7 @@ App.PaginatedContentMixin = Em.Mixin.create({
 			that.set('entities', entities);
 			that.set('loading', false);
 		}).catch(function(jqXHR){
+			if(console) console.log(jqXHR);
 			alert('failed');
 		});
 	},

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
index 00ef215..34644f8 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
@@ -101,6 +101,12 @@ var timelineJsonToDagMap = {
   applicationId: 'otherinfo.applicationId',
   status: 'otherinfo.status',
   diagnostics: 'otherinfo.diagnostics',
+
+  planName: 'otherinfo.dagPlan.dagName',
+  planVersion: 'otherinfo.dagPlan.version',
+  vertices: 'otherinfo.dagPlan.vertices',
+  edges: 'otherinfo.dagPlan.edges',
+
   counterGroups: 'counterGroups'
 };
 
@@ -269,6 +275,7 @@ var timelineJsonToVertexMap = {
   dagID: 'primaryfilters.TEZ_DAG_ID.0',
   processorClassName: 'otherinfo.stats.processorClassName',
   counterGroups: 'counterGroups',
+  inputs: 'inputs',
 
   startTime: 'otherinfo.startTime',
   endTime: 'otherinfo.endTime',
@@ -298,14 +305,26 @@ var timelineJsonToVertexMap = {
 App.VertexSerializer = App.TimelineSerializer.extend({
   _normalizeSingleVertexPayload: function(vertex) {
     var normalizedCounterGroupData = this.normalizeCounterGroupsHelper('vertex', vertex.entity, 
-      vertex);
-    vertex.counterGroups = normalizedCounterGroupData.counterGroupsIDs;
+        vertex);
+        vertex.counterGroups = normalizedCounterGroupData.counterGroupsIDs,
+        vertexInputs = [],
+        inputIds = [];
 
     delete vertex.otherinfo.counters;
 
+    if(vertex.inputs) {
+      vertex.inputs.forEach(function (input, index) {
+        input.entity = vertex.entity + '-input' + index;
+        inputIds.push(input.entity);
+        vertexInputs.push(input);
+      });
+      vertex.inputs = inputIds;
+    }
+
     return {
       vertex: vertex,
       counterGroups: normalizedCounterGroupData.counterGroups,
+      vertexInputs: vertexInputs,
       counters: normalizedCounterGroupData.counters
     };
   },
@@ -315,6 +334,7 @@ App.VertexSerializer = App.TimelineSerializer.extend({
       var normalizedPayload = {
         vertices: [],
         counterGroups: [],
+        vertexInputs: [],
         counters: []
       };
       rawPayload.vertices.forEach(function(vertex){
@@ -322,6 +342,7 @@ App.VertexSerializer = App.TimelineSerializer.extend({
         normalizedPayload.vertices.push(n.vertex);
         [].push.apply(normalizedPayload.counterGroups, n.counterGroups);
         [].push.apply(normalizedPayload.counters, n.counters);
+        [].push.apply(normalizedPayload.vertexInputs, n.vertexInputs);
       }, this);
       
       // delete so that we dont hang on to the json data.
@@ -338,6 +359,44 @@ App.VertexSerializer = App.TimelineSerializer.extend({
   },
 });
 
+App.VertexInputSerializer = App.TimelineSerializer.extend({
+  _map: {
+    id: 'entity',
+    inputName: 'name',
+    inputClass: 'class',
+    inputInitializer: 'initializer',
+    configs: 'configs'
+  },
+  _normalizeData: function(data) {
+    var userPayload = JSON.parse(data.userPayloadAsText || null),
+        store = this.get('store'),
+        configs,
+        configKey,
+        configIndex = 0,
+        id;
+
+    data.configs = [];
+
+    if(userPayload) {
+      configs = userPayload.config || userPayload.dist;
+      for(configKey in configs) {
+        id = data.entity + configIndex++;
+        data.configs.push(id);
+        store.push('KVDatum', {
+          id: id,
+          key: configKey,
+          value: configs[configKey]
+        });
+      }
+    }
+
+    return data;
+  },
+  normalize: function(type, hash, prop) {
+    return Em.JsonMapper.map(this._normalizeData(hash), this._map);
+  }
+});
+
 var timelineJsonToAppDetailMap = {
   id: 'appId',
   attemptId: 'currentAppAttemptId',

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/scripts/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/dag.js b/tez-ui/src/main/webapp/app/scripts/models/dag.js
index 8a74b4b..fa40f5a 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/dag.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/dag.js
@@ -36,7 +36,9 @@ App.Dag = App.AbstractEntity.extend({
 
 	// application ID of this dag.
 	applicationId: DS.attr('string'),
-  app: DS.belongsTo('appDetail', {async: true}),
+
+  tezApp: DS.belongsTo('tezApp', {async: true}),
+  appDetail: DS.belongsTo('appDetail', {async: true}),
 
 	// status
 	status: DS.attr('string'),
@@ -44,9 +46,11 @@ App.Dag = App.AbstractEntity.extend({
 	// diagnostics info if any.
 	diagnostics: DS.attr('string'),
 
-	//vertices: DS.hasMany('vertex'),
-
-	//edges: DS.hasMany('edge'),
+  // Dag plan reated data
+  planName: DS.attr('string'),
+  planVersion: DS.attr('number'),
+  vertices: DS.attr('array'), // Serialize when required
+  edges: DS.attr('array'), // Serialize when required
 
   counterGroups: DS.hasMany('counterGroup', { inverse: 'parent' })
 });
@@ -217,6 +221,8 @@ App.Vertex = DS.Model.extend({
 
   recordWriteCount: DS.attr('number'),
 
+  inputs: DS.hasMany('vertexInput'),
+
   totalReadBytes: function () {
     return this.get('fileReadBytes') + this.get('hdfsReadBytes');
   }.property('fileReadBytes', 'hdfsReadBytes'),
@@ -238,6 +244,16 @@ App.Vertex = DS.Model.extend({
   }.property('duration')
 });
 
+App.VertexInput = DS.Model.extend({
+  entity: DS.attr('string'),
+
+  inputName: DS.attr('string'),
+  inputClass: DS.attr('string'),
+  inputInitializer: DS.attr('string'),
+
+  configs: DS.hasMany('kVData', { async: false })
+});
+
 App.AppDetail = DS.Model.extend({
   attemptId: DS.attr('string'),
 

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/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 50615a5..43deef0 100644
--- a/tez-ui/src/main/webapp/app/scripts/router.js
+++ b/tez-ui/src/main/webapp/app/scripts/router.js
@@ -32,6 +32,10 @@ App.Router.map(function() {
 
   this.resource('vertex', {path: '/vertex/:vertex_id'}, function(){
     this.route('tasks');
+    this.route('inputs');
+    this.resource('vertexInput', {path: '/input/:input_id'}, function(){
+      this.route('configs');
+    });
     this.route('counters');
     this.route('details');
     this.route('swimlane');
@@ -159,6 +163,13 @@ App.VertexSwimlaneRoute = Em.Route.extend({
   }
 });
 
+App.VertexInputsRoute = Em.Route.extend({
+  setupController: function(controller, model) {
+    this._super(controller, model);
+    controller.loadEntities();
+  }
+});
+
 App.DagTasksRoute = Em.Route.extend({
   queryParams: {
     status: App.Helpers.misc.defaultQueryParamsConfig,
@@ -204,11 +215,28 @@ App.TaskAttemptsRoute = Em.Route.extend({
   }
 });
 
+App.VertexInputConfigsRoute = App.TezAppConfigsRoute = Em.Route.extend({
+  renderTemplate: function() {
+    this.render('common/configs');
+  }
+});
+
+App.VertexInputRoute = Em.Route.extend({
+  model: function (params) {
+    var model = this.modelFor('vertex');
+    return model.get('inputs').findBy('id', params.input_id);
+  },
+  setupController: function(controller, model) {
+    this._super(controller, model);
+  }
+});
+
 App.TezAppRoute = Em.Route.extend({
   model: function(params) {
     var store = this.store;
-    return store.find('tezApp', 'tez_' + params.app_id).then(function(tezApp){
-      return store.find('appDetail', tezApp.get('appId')).then(function(appDetails){
+    return store.find('tezApp', 'tez_' + params.app_id).then(function (tezApp){
+      if(!tezApp.get('appId')) return tezApp;
+      return store.find('appDetail', tezApp.get('appId')).then(function (appDetails){
         tezApp.set('appDetail', appDetails);
         return tezApp;
       });
@@ -229,11 +257,3 @@ App.TezAppDagsRoute = Em.Route.extend({
     controller.loadData();
   }
 });
-
-App.TezAppConfigsRoute = Em.Route.extend({
-  setupController: function(controller, model) {
-    this._super(controller, model);
-    controller.loadData();
-  }
-});
-

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/styles/main.less
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/styles/main.less b/tez-ui/src/main/webapp/app/styles/main.less
index 240b82d..2a6bd91 100644
--- a/tez-ui/src/main/webapp/app/styles/main.less
+++ b/tez-ui/src/main/webapp/app/styles/main.less
@@ -163,7 +163,7 @@ div.indent {
   }
 
   th:first-child {
-        width: 70%;
+    width: 70%;
   }
 
   tr {
@@ -176,6 +176,29 @@ div.indent {
   }
 }
 
+.kv-table {
+  width: 100%;
+  margin-top: 10px;
+  table-layout: fixed;
+
+  th, td {
+    border: 1px solid #dcdcdc;
+    padding: 5px 5px;
+    width: 50%;
+    overflow: scroll;
+  }
+
+  th, td.filter {
+    background-color: #f0f0f0;
+    font-style: italic;
+    font-weight: bold;
+  }
+
+  input[type=search] {
+    width: 100%;
+  }
+}
+
 .inline-display {
 	display: inline;
 }

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/templates/common/configs.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/common/configs.hbs b/tez-ui/src/main/webapp/app/templates/common/configs.hbs
new file mode 100644
index 0000000..dfc18d3
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/common/configs.hbs
@@ -0,0 +1,21 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class='table-container'>
+  {{kv-table-component data=configs}}
+</div>

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/templates/components/kv-table.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/components/kv-table.hbs b/tez-ui/src/main/webapp/app/templates/components/kv-table.hbs
new file mode 100644
index 0000000..0a8c110
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/components/kv-table.hbs
@@ -0,0 +1,39 @@
+{{!
+* 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.
+}}
+
+<table class='kv-table'>
+  <thead>
+    <tr>
+      <th>Key</th>
+      <th>Value</th>
+    </tr>
+    <tr>
+      <td class='filter' colspan='2'>
+        {{input size='60' type='search' results='1' placeholder='Search...' valueBinding='filterExp'}}
+      </td>
+    </tr>
+    <tbody>
+      {{#each kv in filteredKVs}}
+        <tr>
+          <td>{{unbound kv.key}}</td>
+          <td>{{unbound kv.value}}</td>
+        </tr>
+      {{/each}}
+    </tbody>
+  </thead>
+</table>

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs b/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
deleted file mode 100644
index 4662279..0000000
--- a/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
+++ /dev/null
@@ -1,46 +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.
-}}
-
-{{#unless loading}}
-  <div class='margin-small'>
-    <span class='align-right'>
-      {{page-nav-component
-        hasPrev=hasPrev
-        hasNext=hasNext
-        navNext='navigateNext'
-        navPrev='navigatePrev'
-        navFirst='navigateFirst'
-      }}
-    </span>
-    <div class='align-clear'> </div>
-  </div>
-
-  <div class='table-container'>
-  {{extended-table-component 
-    hasFooter=false
-    enableContentSelection=true
-    columnsBinding="columns"
-    contentBinding="sortedContent"
-    forceFillColumns=true
-    hasFilter=true
-    onFilterUpdated='filterUpdated'
-  }}
-  </div>
-{{else}}
-  {{partial 'utils/loadingSpinner'}}
-{{/unless}}

http://git-wip-us.apache.org/repos/asf/tez/blob/7f8198f1/tez-ui/src/main/webapp/app/templates/vertex/inputs.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/vertex/inputs.hbs b/tez-ui/src/main/webapp/app/templates/vertex/inputs.hbs
new file mode 100644
index 0000000..dfee676
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/vertex/inputs.hbs
@@ -0,0 +1,49 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements.  See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership.  The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License.  You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+{{#unless loading}}
+  {{#if inputsAvailable}}
+    <div class='margin-small'>
+      <span class='align-right'>
+        {{page-nav-component
+          hasPrev=hasPrev
+          hasNext=hasNext
+          navNext='navigateNext'
+          navPrev='navigatePrev'
+          navFirst='navigateFirst'
+        }}
+      </span>
+      <div class='align-clear'> </div>
+    </div>
+
+    <div class='table-container'>
+    {{extended-table-component
+      hasFooter=false
+      enableContentSelection=false
+      columnsBinding="columns"
+      contentBinding="sortedContent"
+      forceFillColumns=true
+      hasFilter=true
+    }}
+    </div>
+  {{else}}
+    <h1>Inputs are not available!</h1>
+  {{/if}}
+{{else}}
+  {{partial 'utils/loadingSpinner'}}
+{{/unless}}