You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by sr...@apache.org on 2016/01/28 19:13:32 UTC

[3/3] tez git commit: TEZ-3060. Tez UI 2: Activate auto-refresh (sree)

TEZ-3060. Tez UI 2: Activate auto-refresh (sree)


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

Branch: refs/heads/TEZ-2980
Commit: 6f366403d1a83ce34b3a546b42ce67be48ea9299
Parents: 852247b
Author: Sreenath Somarajapuram <sr...@apache.org>
Authored: Thu Jan 28 23:41:36 2016 +0530
Committer: Sreenath Somarajapuram <sr...@apache.org>
Committed: Thu Jan 28 23:41:36 2016 +0530

----------------------------------------------------------------------
 TEZ-2980-CHANGES.txt                            |   1 +
 tez-ui2/src/main/webapp/app/adapters/am.js      |   4 +-
 tez-ui2/src/main/webapp/app/adapters/app-rm.js  |  22 +++
 .../src/main/webapp/app/adapters/attempt-am.js  |  22 +++
 tez-ui2/src/main/webapp/app/adapters/dag-am.js  |  22 +++
 tez-ui2/src/main/webapp/app/adapters/loader.js  |   2 +-
 tez-ui2/src/main/webapp/app/adapters/task-am.js |  22 +++
 .../src/main/webapp/app/adapters/vertex-am.js   |  22 +++
 .../main/webapp/app/components/tab-n-refresh.js |   7 +-
 .../src/main/webapp/app/controllers/abstract.js |   7 +-
 tez-ui2/src/main/webapp/app/controllers/app.js  |   4 +-
 .../main/webapp/app/controllers/app/configs.js  |   4 +-
 .../src/main/webapp/app/controllers/app/dags.js |   7 +-
 .../src/main/webapp/app/controllers/attempt.js  |   4 +-
 .../webapp/app/controllers/attempt/counters.js  |   4 +-
 .../webapp/app/controllers/counters-page.js     |  63 ---------
 .../webapp/app/controllers/counters-table.js    |  74 ++++++++++
 tez-ui2/src/main/webapp/app/controllers/dag.js  |   4 +-
 .../main/webapp/app/controllers/dag/attempts.js |   7 +-
 .../main/webapp/app/controllers/dag/counters.js |   4 +-
 .../main/webapp/app/controllers/dag/tasks.js    |   7 +-
 .../main/webapp/app/controllers/dag/vertices.js |   7 +-
 tez-ui2/src/main/webapp/app/controllers/dags.js |   7 +-
 .../main/webapp/app/controllers/multi-table.js  |  37 +++++
 tez-ui2/src/main/webapp/app/controllers/page.js |   9 +-
 .../src/main/webapp/app/controllers/parent.js   |  30 ++++
 .../main/webapp/app/controllers/table-page.js   | 135 ------------------
 .../src/main/webapp/app/controllers/table.js    | 138 +++++++++++++++++++
 tez-ui2/src/main/webapp/app/controllers/task.js |   6 +-
 .../webapp/app/controllers/task/attempts.js     |   7 +-
 .../webapp/app/controllers/task/counters.js     |   4 +-
 .../src/main/webapp/app/controllers/vertex.js   |   6 +-
 .../webapp/app/controllers/vertex/attempts.js   |   7 +-
 .../webapp/app/controllers/vertex/counters.js   |   4 +-
 .../main/webapp/app/controllers/vertex/tasks.js |   7 +-
 tez-ui2/src/main/webapp/app/entities/am.js      |  58 ++++++++
 .../src/main/webapp/app/entities/attempt-am.js  |  23 ++++
 tez-ui2/src/main/webapp/app/entities/entity.js  | 138 ++++++++++++++-----
 tez-ui2/src/main/webapp/app/entities/task-am.js |  23 ++++
 .../src/main/webapp/app/entities/vertex-am.js   |  23 ++++
 .../main/webapp/app/initializers/entities.js    |   1 +
 .../webapp/app/mixins/auto-counter-column.js    |  14 +-
 tez-ui2/src/main/webapp/app/models/abstract.js  |  21 +++
 tez-ui2/src/main/webapp/app/models/ahs-app.js   |   2 -
 .../src/main/webapp/app/models/am-timeline.js   |  46 +++++++
 tez-ui2/src/main/webapp/app/models/am.js        |  31 +++++
 tez-ui2/src/main/webapp/app/models/app-rm.js    |  22 +++
 tez-ui2/src/main/webapp/app/models/app.js       |  16 ---
 .../src/main/webapp/app/models/attempt-am.js    |  22 +++
 tez-ui2/src/main/webapp/app/models/attempt.js   |  53 +++----
 tez-ui2/src/main/webapp/app/models/dag-am.js    |  22 +++
 tez-ui2/src/main/webapp/app/models/dag.js       |  39 +++---
 tez-ui2/src/main/webapp/app/models/rm.js        |  26 ++++
 tez-ui2/src/main/webapp/app/models/task-am.js   |  22 +++
 tez-ui2/src/main/webapp/app/models/task.js      |  48 +++----
 tez-ui2/src/main/webapp/app/models/timeline.js  |  11 +-
 tez-ui2/src/main/webapp/app/models/vertex-am.js |  22 +++
 tez-ui2/src/main/webapp/app/models/vertex.js    |  37 ++---
 tez-ui2/src/main/webapp/app/router.js           |   2 +
 tez-ui2/src/main/webapp/app/routes/abstract.js  |   7 +-
 .../src/main/webapp/app/routes/am-pollster.js   |  88 ++++++++++++
 .../src/main/webapp/app/routes/app/configs.js   |   6 +-
 tez-ui2/src/main/webapp/app/routes/app/dags.js  |   4 +-
 tez-ui2/src/main/webapp/app/routes/app/index.js |   8 +-
 .../src/main/webapp/app/routes/application.js   |   5 +
 tez-ui2/src/main/webapp/app/routes/attempt.js   |   2 +-
 .../main/webapp/app/routes/attempt/counters.js  |   4 +-
 .../src/main/webapp/app/routes/attempt/index.js |   4 +-
 .../src/main/webapp/app/routes/dag/attempts.js  |   4 +-
 .../src/main/webapp/app/routes/dag/counters.js  |   4 +-
 tez-ui2/src/main/webapp/app/routes/dag/index.js |   4 +-
 tez-ui2/src/main/webapp/app/routes/dag/tasks.js |   4 +-
 .../src/main/webapp/app/routes/dag/vertices.js  |   4 +-
 tez-ui2/src/main/webapp/app/routes/dags.js      |   6 +-
 .../main/webapp/app/routes/multi-am-pollster.js |  35 +++++
 tez-ui2/src/main/webapp/app/routes/pollster.js  |  65 +++++++++
 .../webapp/app/routes/single-am-pollster.js     |  34 +++++
 tez-ui2/src/main/webapp/app/routes/task.js      |   2 +-
 .../src/main/webapp/app/routes/task/attempts.js |   4 +-
 .../src/main/webapp/app/routes/task/counters.js |   4 +-
 .../src/main/webapp/app/routes/task/index.js    |   4 +-
 .../main/webapp/app/routes/vertex/attempts.js   |   4 +-
 .../main/webapp/app/routes/vertex/counters.js   |   4 +-
 .../src/main/webapp/app/routes/vertex/index.js  |   4 +-
 .../src/main/webapp/app/routes/vertex/tasks.js  |   4 +-
 tez-ui2/src/main/webapp/app/serializers/am.js   |  41 ++++++
 .../src/main/webapp/app/serializers/app-rm.js   |  33 +++++
 .../main/webapp/app/serializers/attempt-am.js   |  23 ++++
 .../src/main/webapp/app/serializers/dag-am.js   |  28 ++++
 .../src/main/webapp/app/serializers/loader.js   |   1 +
 tez-ui2/src/main/webapp/app/serializers/rm.js   |  28 ++++
 .../src/main/webapp/app/serializers/task-am.js  |  23 ++++
 .../src/main/webapp/app/serializers/timeline.js |   4 +-
 .../main/webapp/app/serializers/vertex-am.js    |  23 ++++
 tez-ui2/src/main/webapp/app/services/hosts.js   |   4 +
 tez-ui2/src/main/webapp/app/services/loader.js  |  79 +++++------
 .../src/main/webapp/app/services/pollster.js    |  83 +++++++++++
 tez-ui2/src/main/webapp/app/templates/app.hbs   |   2 +-
 .../src/main/webapp/app/templates/app/dags.hbs  |   4 +-
 .../src/main/webapp/app/templates/attempt.hbs   |   2 +-
 .../webapp/app/templates/attempt/counters.hbs   |   2 +-
 .../main/webapp/app/templates/attempt/index.hbs |   8 +-
 .../app/templates/components/tab-n-refresh.hbs  |   6 +-
 tez-ui2/src/main/webapp/app/templates/dag.hbs   |   2 +-
 .../main/webapp/app/templates/dag/attempts.hbs  |   4 +-
 .../main/webapp/app/templates/dag/counters.hbs  |   2 +-
 .../src/main/webapp/app/templates/dag/index.hbs |   4 +
 .../src/main/webapp/app/templates/dag/tasks.hbs |   4 +-
 .../main/webapp/app/templates/dag/vertices.hbs  |   4 +-
 tez-ui2/src/main/webapp/app/templates/dags.hbs  |   4 +-
 tez-ui2/src/main/webapp/app/templates/task.hbs  |   2 +-
 .../main/webapp/app/templates/task/attempts.hbs |   4 +-
 .../main/webapp/app/templates/task/counters.hbs |   2 +-
 .../main/webapp/app/templates/task/index.hbs    |   8 +-
 .../src/main/webapp/app/templates/vertex.hbs    |   2 +-
 .../webapp/app/templates/vertex/attempts.hbs    |   4 +-
 .../webapp/app/templates/vertex/counters.hbs    |   2 +-
 .../main/webapp/app/templates/vertex/index.hbs  |   4 +
 .../main/webapp/app/templates/vertex/tasks.hbs  |   4 +-
 .../app/utils/counter-column-definition.js      |   2 +-
 .../src/main/webapp/config/default-app-conf.js  |  13 +-
 tez-ui2/src/main/webapp/package.json            |   2 +-
 .../main/webapp/tests/unit/adapters/am-test.js  |  19 +++
 .../webapp/tests/unit/adapters/app-rm-test.js   |  29 ++++
 .../tests/unit/adapters/attempt-am-test.js      |  29 ++++
 .../webapp/tests/unit/adapters/dag-am-test.js   |  29 ++++
 .../webapp/tests/unit/adapters/task-am-test.js  |  29 ++++
 .../tests/unit/adapters/vertex-am-test.js       |  29 ++++
 .../tests/unit/controllers/abstract-test.js     |   1 +
 .../tests/unit/controllers/app/dags-test.js     |   3 +-
 .../unit/controllers/counters-page-test.js      |  97 -------------
 .../unit/controllers/counters-table-test.js     |  91 ++++++++++++
 .../tests/unit/controllers/dag/attempts-test.js |   5 +-
 .../tests/unit/controllers/dag/tasks-test.js    |   5 +-
 .../tests/unit/controllers/dag/vertices-test.js |   5 +-
 .../tests/unit/controllers/multi-table-test.js  |  40 ++++++
 .../tests/unit/controllers/parent-test.js       |  36 +++++
 .../tests/unit/controllers/table-page-test.js   |  64 ---------
 .../webapp/tests/unit/controllers/table-test.js |  64 +++++++++
 .../unit/controllers/task/attempts-test.js      |   5 +-
 .../unit/controllers/vertex/attempts-test.js    |   5 +-
 .../tests/unit/controllers/vertex/tasks-test.js |   5 +-
 .../main/webapp/tests/unit/entities/am-test.js  |  33 +++++
 .../tests/unit/entities/attempt-am-test.js      |  31 +++++
 .../webapp/tests/unit/entities/entity-test.js   |  95 +++----------
 .../webapp/tests/unit/entities/task-am-test.js  |  31 +++++
 .../tests/unit/entities/vertex-am-test.js       |  31 +++++
 .../unit/mixins/auto-counter-column-test.js     |  32 +++--
 .../webapp/tests/unit/models/abstract-test.js   |   5 +
 .../webapp/tests/unit/models/ahs-app-test.js    |   2 +
 .../main/webapp/tests/unit/models/am-test.js    |  31 +++++
 .../tests/unit/models/am-timeline-test.js       |  34 +++++
 .../webapp/tests/unit/models/app-rm-test.js     |  30 ++++
 .../webapp/tests/unit/models/attempt-am-test.js |  30 ++++
 .../webapp/tests/unit/models/attempt-test.js    |  17 ++-
 .../webapp/tests/unit/models/dag-am-test.js     |  30 ++++
 .../main/webapp/tests/unit/models/dag-test.js   |   1 +
 .../main/webapp/tests/unit/models/rm-test.js    |  30 ++++
 .../webapp/tests/unit/models/task-am-test.js    |  30 ++++
 .../main/webapp/tests/unit/models/task-test.js  |  12 +-
 .../webapp/tests/unit/models/timeline-test.js   |  16 +--
 .../webapp/tests/unit/models/vertex-am-test.js  |  30 ++++
 .../webapp/tests/unit/models/vertex-test.js     |  22 ++-
 .../tests/unit/routes/am-pollster-test.js       |  34 +++++
 .../tests/unit/routes/multi-am-pollster-test.js |  32 +++++
 .../webapp/tests/unit/routes/pollster-test.js   |  39 ++++++
 .../unit/routes/single-am-pollster-test.js      |  32 +++++
 .../tests/unit/routes/vertex/tasks-test.js      |   7 +-
 .../webapp/tests/unit/serializers/am-test.js    |  30 ++++
 .../tests/unit/serializers/app-rm-test.js       |  30 ++++
 .../tests/unit/serializers/attempt-am-test.js   |  31 +++++
 .../tests/unit/serializers/dag-am-test.js       |  30 ++++
 .../webapp/tests/unit/serializers/rm-test.js    |  30 ++++
 .../tests/unit/serializers/task-am-test.js      |  31 +++++
 .../tests/unit/serializers/vertex-am-test.js    |  31 +++++
 .../webapp/tests/unit/services/loader-test.js   |  74 ++++------
 .../webapp/tests/unit/services/pollster-test.js |  29 ++++
 .../utils/counter-column-definition-test.js     |   4 +-
 178 files changed, 3009 insertions(+), 842 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/TEZ-2980-CHANGES.txt
----------------------------------------------------------------------
diff --git a/TEZ-2980-CHANGES.txt b/TEZ-2980-CHANGES.txt
index f5660a5..60eb715 100644
--- a/TEZ-2980-CHANGES.txt
+++ b/TEZ-2980-CHANGES.txt
@@ -26,3 +26,4 @@ ALL CHANGES:
   TEZ-3064. Tez UI 2: Add All DAGs filters
   TEZ-3059. Tez UI 2: Make refresh functional
   TEZ-3070. Tez UI 2: Jenkins build is failing
+  TEZ-3060. Tez UI 2: Activate auto-refresh

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/am.js b/tez-ui2/src/main/webapp/app/adapters/am.js
index f80cdd5..85f3d27 100644
--- a/tez-ui2/src/main/webapp/app/adapters/am.js
+++ b/tez-ui2/src/main/webapp/app/adapters/am.js
@@ -21,5 +21,7 @@ import AbstractAdapter from './abstract';
 export default AbstractAdapter.extend({
   serverName: "am",
 
-  // Any am specific adapter changes must be added here
+  queryRecord: function(store, type, query) {
+    return this.query(store, type, query);
+  },
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/app-rm.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/app-rm.js b/tez-ui2/src/main/webapp/app/adapters/app-rm.js
new file mode 100644
index 0000000..b61e391
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/app-rm.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import RMAdapter from './rm';
+
+export default RMAdapter.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/attempt-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/attempt-am.js b/tez-ui2/src/main/webapp/app/adapters/attempt-am.js
new file mode 100644
index 0000000..39cd2a4
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/attempt-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMAdapter from './am';
+
+export default AMAdapter.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/dag-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/dag-am.js b/tez-ui2/src/main/webapp/app/adapters/dag-am.js
new file mode 100644
index 0000000..39cd2a4
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/dag-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMAdapter from './am';
+
+export default AMAdapter.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/loader.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/loader.js b/tez-ui2/src/main/webapp/app/adapters/loader.js
index d4b502c..f63bd07 100644
--- a/tez-ui2/src/main/webapp/app/adapters/loader.js
+++ b/tez-ui2/src/main/webapp/app/adapters/loader.js
@@ -25,7 +25,7 @@ export default DS.RESTAdapter.extend({
   _isLoader: true,
 
   buildURL: function(modelName, id, snapshot, requestType, query, params) {
-    var url = this._super(modelName, id, snapshot, null, query);
+    var url = this._super(modelName, id, snapshot, requestType, query);
     return params ? MoreString.fmt(url, params) : url;
   },
 

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/task-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/task-am.js b/tez-ui2/src/main/webapp/app/adapters/task-am.js
new file mode 100644
index 0000000..39cd2a4
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/task-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMAdapter from './am';
+
+export default AMAdapter.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/adapters/vertex-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/adapters/vertex-am.js b/tez-ui2/src/main/webapp/app/adapters/vertex-am.js
new file mode 100644
index 0000000..39cd2a4
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/adapters/vertex-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMAdapter from './am';
+
+export default AMAdapter.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/components/tab-n-refresh.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/components/tab-n-refresh.js b/tez-ui2/src/main/webapp/app/components/tab-n-refresh.js
index 75bac20..6ac6454 100644
--- a/tez-ui2/src/main/webapp/app/components/tab-n-refresh.js
+++ b/tez-ui2/src/main/webapp/app/components/tab-n-refresh.js
@@ -24,13 +24,18 @@ export default Ember.Component.extend({
     this.setApplication();
   },
 
-  autoRefreshEnabled: true,
+  autoRefreshEnabled: false,
+  autoRefreshVisible: true,
 
   setApplication: function () {
     var application = this.get("targetObject.container").lookup('controller:application');
     this.set("application", application);
   },
 
+  autoRefreshObserver: Ember.observer("autoRefreshEnabled", function () {
+    this.get('targetObject').send('autoRefreshChanged', this.get("autoRefreshEnabled"));
+  }),
+
   normalizedTabs: Ember.computed("tabs", "application.currentPath", function () {
     var tabs = this.get("tabs") || [],
         activeRouteName = this.get("application.currentPath");

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/abstract.js b/tez-ui2/src/main/webapp/app/controllers/abstract.js
index 816e7d1..863a63f 100644
--- a/tez-ui2/src/main/webapp/app/controllers/abstract.js
+++ b/tez-ui2/src/main/webapp/app/controllers/abstract.js
@@ -24,14 +24,19 @@ export default Ember.Controller.extend(NameMixin, {
   // Must be set by inheriting classes
   breadcrumbs: null,
 
-  // Must be set from route
+  // Must be set from abstract route
   loadTime: null,
+  isLoading: false,
 
   init: function () {
     this._super();
     Ember.run.later(this, "setBreadcrumbs");
   },
 
+  loaded: Ember.computed("model", "isLoading", function () {
+    return this.get("model") && !this.get("isLoading");
+  }),
+
   crumbObserver: Ember.observer("breadcrumbs", function () {
     Ember.run.later(this, "setBreadcrumbs");
   }),

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/app.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/app.js b/tez-ui2/src/main/webapp/app/controllers/app.js
index 8333220..f379e80 100644
--- a/tez-ui2/src/main/webapp/app/controllers/app.js
+++ b/tez-ui2/src/main/webapp/app/controllers/app.js
@@ -18,9 +18,9 @@
 
 import Ember from 'ember';
 
-import AbstractController from './abstract';
+import ParentController from './parent';
 
-export default AbstractController.extend({
+export default ParentController.extend({
   breadcrumbs: Ember.computed("model.appID", "model.app.name", function () {
     var name = this.get("model.app.name") || this.get("model.appID");
 

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/app/configs.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/app/configs.js b/tez-ui2/src/main/webapp/app/controllers/app/configs.js
index 517d43b..838abc1 100644
--- a/tez-ui2/src/main/webapp/app/controllers/app/configs.js
+++ b/tez-ui2/src/main/webapp/app/controllers/app/configs.js
@@ -19,12 +19,12 @@
 
 import Ember from 'ember';
 
-import TablePageController from '../table-page';
+import TableController from '../table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
 var MoreObject = more.Object;
 
-export default TablePageController.extend({
+export default TableController.extend({
   searchText: "tez",
 
   breadcrumbs: [{

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/app/dags.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/app/dags.js b/tez-ui2/src/main/webapp/app/controllers/app/dags.js
index 547c4ee..b3e855a 100644
--- a/tez-ui2/src/main/webapp/app/controllers/app/dags.js
+++ b/tez-ui2/src/main/webapp/app/controllers/app/dags.js
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
-export default TablePageController.extend({
+export default MultiTableController.extend({
   breadcrumbs: [{
     text: "DAGs",
     routeName: "app.dags",
@@ -49,7 +49,8 @@ export default TablePageController.extend({
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/attempt.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/attempt.js b/tez-ui2/src/main/webapp/app/controllers/attempt.js
index 64c8a67..b10fc7f 100644
--- a/tez-ui2/src/main/webapp/app/controllers/attempt.js
+++ b/tez-ui2/src/main/webapp/app/controllers/attempt.js
@@ -18,9 +18,9 @@
 
 import Ember from 'ember';
 
-import AbstractController from './abstract';
+import ParentController from './parent';
 
-export default AbstractController.extend({
+export default ParentController.extend({
   breadcrumbs: Ember.computed("model.dag", function () {
     var dagName = this.get("model.dag.name"),
         vertexName = this.get("model.vertexName"),

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/attempt/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/attempt/counters.js b/tez-ui2/src/main/webapp/app/controllers/attempt/counters.js
index 9442838..1a93c80 100644
--- a/tez-ui2/src/main/webapp/app/controllers/attempt/counters.js
+++ b/tez-ui2/src/main/webapp/app/controllers/attempt/counters.js
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import CountersPageController from '../counters-page';
+import CountersTableController from '../counters-table';
 
-export default CountersPageController.extend({
+export default CountersTableController.extend({
   breadcrumbs: [{
     text: "Attempt Counters",
     routeName: "attempt.counters",

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/counters-page.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/counters-page.js b/tez-ui2/src/main/webapp/app/controllers/counters-page.js
deleted file mode 100644
index ef22ef1..0000000
--- a/tez-ui2/src/main/webapp/app/controllers/counters-page.js
+++ /dev/null
@@ -1,63 +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.
- */
-
-import Ember from 'ember';
-
-import TablePageController from './table-page';
-import ColumnDefinition from 'em-table/utils/column-definition';
-
-export default TablePageController.extend({
-  columns: ColumnDefinition.make([{
-    id: 'groupName',
-    headerTitle: 'Group Name',
-    contentPath: 'groupName',
-  }, {
-    id: 'counterName',
-    headerTitle: 'Counter Name',
-    contentPath: 'counterName',
-  }, {
-    id: 'counterValue',
-    headerTitle: 'Counter Value',
-    contentPath: 'counterValue',
-  }]),
-
-  counters: Ember.computed("model.counterGroups", function () {
-    var counterGroups = this.get("model.counterGroups"),
-        counterRows = [];
-
-    if(counterGroups) {
-      counterGroups.forEach(function (group) {
-        var counterGroupName = group.counterGroupName,
-            counters = group.counters;
-
-        if(counters) {
-          counterGroupName = counterGroupName.substr(counterGroupName.lastIndexOf('.') + 1);
-          counters.forEach(function (counter) {
-            counterRows.push(Ember.Object.create({
-              groupName: counterGroupName,
-              counterName: counter.counterName,
-              counterValue: counter.counterValue
-            }));
-          });
-        }
-      });
-    }
-
-    return Ember.A(counterRows);
-  })
-});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/counters-table.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/counters-table.js b/tez-ui2/src/main/webapp/app/controllers/counters-table.js
new file mode 100644
index 0000000..42361b4
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/controllers/counters-table.js
@@ -0,0 +1,74 @@
+/*global more*/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+import TableController from './table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+var MoreObject = more.Object;
+
+export default TableController.extend({
+  counters: Ember.A(),
+  countersCount: 0, // Because Ember.Array doesn't handle length well
+
+  columns: ColumnDefinition.make([{
+    id: 'groupName',
+    headerTitle: 'Group Name',
+    contentPath: 'groupName',
+  }, {
+    id: 'counterName',
+    headerTitle: 'Counter Name',
+    contentPath: 'counterName',
+  }, {
+    id: 'counterValue',
+    headerTitle: 'Counter Value',
+    contentPath: 'counterValue',
+    observePath: true
+  }]),
+
+  _countersObserver: Ember.observer("model.counterGroupsHash", function () {
+    var counterGroupsHash = this.get("model.counterGroupsHash"),
+        counters = this.get("counters"),
+        counterIndex = 0;
+
+    if(counterGroupsHash) {
+      MoreObject.forEach(counterGroupsHash, function (groupName, countersHash) {
+        if(countersHash) {
+          MoreObject.forEach(countersHash, function (counterName, counterValue) {
+            let counterRow = counters.get(counterIndex);
+            if(!counterRow) {
+              counterRow = Ember.Object.create();
+              counters.push(counterRow);
+            }
+
+            counterRow.setProperties({
+              groupName: groupName,
+              counterName: counterName,
+              counterValue: counterValue
+            });
+            counterIndex++;
+          });
+        }
+      });
+    }
+
+    this.set("countersCount", counterIndex);
+  })
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag.js b/tez-ui2/src/main/webapp/app/controllers/dag.js
index 14f9df6..f2b04d1 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag.js
@@ -18,9 +18,9 @@
 
 import Ember from 'ember';
 
-import AbstractController from './abstract';
+import ParentController from './parent';
 
-export default AbstractController.extend({
+export default ParentController.extend({
   breadcrumbs: Ember.computed("model", function () {
     var name = this.get("model.name");
 

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dag/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/attempts.js b/tez-ui2/src/main/webapp/app/controllers/dag/attempts.js
index d9cb9e9..94bca3e 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag/attempts.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag/attempts.js
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
-export default TablePageController.extend({
+export default MultiTableController.extend({
   breadcrumbs: [{
     text: "All Task Attempts",
     routeName: "dag.attempts",
@@ -65,7 +65,8 @@ export default TablePageController.extend({
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dag/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/counters.js b/tez-ui2/src/main/webapp/app/controllers/dag/counters.js
index c4fbea6..c54fd7e 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag/counters.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag/counters.js
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import CountersPageController from '../counters-page';
+import CountersTableController from '../counters-table';
 
-export default CountersPageController.extend({
+export default CountersTableController.extend({
   breadcrumbs: [{
     text: "DAG Counters",
     routeName: "dag.counters",

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dag/tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/tasks.js b/tez-ui2/src/main/webapp/app/controllers/dag/tasks.js
index 1a5c776..58e0163 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag/tasks.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag/tasks.js
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
-export default TablePageController.extend({
+export default MultiTableController.extend({
   breadcrumbs: [{
     text: "All Tasks",
     routeName: "dag.tasks",
@@ -53,7 +53,8 @@ export default TablePageController.extend({
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dag/vertices.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dag/vertices.js b/tez-ui2/src/main/webapp/app/controllers/dag/vertices.js
index b20a558..1b9f136 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dag/vertices.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dag/vertices.js
@@ -16,10 +16,10 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
-export default TablePageController.extend({
+export default MultiTableController.extend({
   breadcrumbs: [{
     text: "All Vertices",
     routeName: "dag.vertices",
@@ -45,7 +45,8 @@ export default TablePageController.extend({
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/dags.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/dags.js b/tez-ui2/src/main/webapp/app/controllers/dags.js
index d35d8f7..021a1e0 100644
--- a/tez-ui2/src/main/webapp/app/controllers/dags.js
+++ b/tez-ui2/src/main/webapp/app/controllers/dags.js
@@ -18,11 +18,11 @@
 
 import Ember from 'ember';
 
-import TablePageController from './table-page';
+import TableController from './table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 import TableDefinition from 'em-table/utils/table-definition';
 
-export default TablePageController.extend({
+export default TableController.extend({
 
   queryParams: ["dagName", "dagID", "submitter", "status", "appID", "contextID", "pageNo"],
   dagName: "",
@@ -75,7 +75,8 @@ export default TablePageController.extend({
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/multi-table.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/multi-table.js b/tez-ui2/src/main/webapp/app/controllers/multi-table.js
new file mode 100644
index 0000000..3a11830
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/controllers/multi-table.js
@@ -0,0 +1,37 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+import TableController from './table';
+import CounterColumnDefinition from '../utils/counter-column-definition';
+
+export default TableController.extend({
+
+  _visibleColumnsObserver: Ember.on("init", Ember.observer("visibleColumns", function () {
+    Ember.run.later(this, "sendCountersChanged");
+  })),
+
+  sendCountersChanged: function () {
+    var visibleCounters = this.get("visibleColumns").filter(function (definition) {
+      return definition instanceof CounterColumnDefinition;
+    });
+    this.send("countersToPollChanged", visibleCounters);
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/page.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/page.js b/tez-ui2/src/main/webapp/app/controllers/page.js
index 84882a8..14ad6b5 100644
--- a/tez-ui2/src/main/webapp/app/controllers/page.js
+++ b/tez-ui2/src/main/webapp/app/controllers/page.js
@@ -16,15 +16,8 @@
  * limitations under the License.
  */
 
-import Ember from 'ember';
-
 import AbstractController from './abstract';
 
 export default AbstractController.extend({
-  // Must be set from route
-  isLoading: false,
-
-  loaded: Ember.computed("model", "isLoading", function () {
-    return this.get("model") && !this.get("isLoading");
-  }),
+  // Any page specific
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/parent.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/parent.js b/tez-ui2/src/main/webapp/app/controllers/parent.js
new file mode 100644
index 0000000..089ed77
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/controllers/parent.js
@@ -0,0 +1,30 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+import AbstractController from './abstract';
+
+export default AbstractController.extend({
+  polling: Ember.inject.service("pollster"),
+  actions: {
+    autoRefreshChanged: function (state) {
+      this.get("polling").set("active", state);
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/table-page.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/table-page.js b/tez-ui2/src/main/webapp/app/controllers/table-page.js
deleted file mode 100644
index 12f4715..0000000
--- a/tez-ui2/src/main/webapp/app/controllers/table-page.js
+++ /dev/null
@@ -1,135 +0,0 @@
-/*global more*/
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-import Ember from 'ember';
-
-import PageController from './page';
-import TableDefinition from 'em-table/utils/table-definition';
-import isIOCounter from '../utils/misc';
-
-import CounterColumnDefinition from '../utils/counter-column-definition';
-
-var MoreObject = more.Object;
-
-export default PageController.extend({
-  queryParams: ["rowCount", "searchText", "sortColumnId", "sortOrder", "pageNo"],
-  rowCount: 10,
-  searchText: "",
-  sortColumnId: "",
-  sortOrder: "",
-  pageNo: 1,
-
-  columns: [],
-
-  headerComponentNames: ['em-table-search-ui', 'table-controls', 'em-table-pagination-ui'],
-
-  visibleColumnIDs: {},
-  columnSelectorTitle: 'Column Selector',
-  columnSelectorMessage: "",
-
-  definition: Ember.computed(function () {
-    return TableDefinition.create({
-      rowCount: this.get("rowCount"),
-      searchText: this.get("searchText"),
-      sortColumnId: this.get("sortColumnId"),
-      sortOrder: this.get("sortOrder"),
-      pageNo: this.get("pageNo")
-    });
-  }),
-
-  storageID: Ember.computed("name", function () {
-    return this.get("name") + ":visibleColumnIDs";
-  }),
-
-  initVisibleColumns: Ember.on("init", Ember.observer("columns", function () { //To reset on entity change
-    var visibleColumnIDs = this.get("localStorage").get(this.get("storageID")) || {};
-
-    this.get('columns').forEach(function (config) {
-      if(visibleColumnIDs[config.id] !== false) {
-        visibleColumnIDs[config.id] = true;
-      }
-    });
-
-    this.set('visibleColumnIDs', visibleColumnIDs);
-  })),
-
-  allColumns: Ember.computed("columns", function () {
-    var columns = this.get("columns"),
-        counters = this.getCounterColumns();
-
-    return columns.concat(CounterColumnDefinition.make(counters));
-  }),
-
-  visibleColumns: Ember.computed('visibleColumnIDs', 'allColumns', function() {
-    var visibleColumnIDs = this.visibleColumnIDs;
-    return this.get('allColumns').filter(function (column) {
-      return visibleColumnIDs[column.get("id")];
-    });
-  }),
-
-  getCounterColumns: function () {
-    return this.get('env.app.tables.defaultColumns.counters');
-  },
-
-  actions: {
-    searchChanged: function (searchText) {
-      this.set("searchText", searchText);
-    },
-    sortChanged: function (sortColumnId, sortOrder) {
-      this.setProperties({
-        sortColumnId,
-        sortOrder
-      });
-    },
-    rowsChanged: function (rowCount) {
-      // Change to rows action in em-table
-      this.set("rowCount", rowCount);
-    },
-    pageChanged: function (pageNum) {
-      this.set("pageNo", pageNum);
-    },
-
-    // Column selection actions
-    openColumnSelector: function () {
-      this.send("openModal", "column-selector", {
-        title: this.get('columnSelectorTitle'),
-        targetObject: this,
-        content: {
-          message: this.get('columnSelectorMessage'),
-          columns: this.get('allColumns'),
-          visibleColumnIDs: this.get('visibleColumnIDs')
-        }
-      });
-    },
-    columnsSelected: function (visibleColumnIDs) {
-      var columnIDs = {};
-
-      MoreObject.forEach(visibleColumnIDs, function (key, value) {
-        if(!isIOCounter(key)) {
-          columnIDs[key] = value;
-        }
-      });
-
-      if(!MoreObject.equals(columnIDs, this.get("visibleColumnIDs"))) {
-        this.get("localStorage").set(this.get("storageID"), columnIDs);
-        this.set('visibleColumnIDs', columnIDs);
-      }
-    }
-  }
-});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/table.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/table.js b/tez-ui2/src/main/webapp/app/controllers/table.js
new file mode 100644
index 0000000..0891e8d
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/controllers/table.js
@@ -0,0 +1,138 @@
+/*global more*/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+import AbstractController from './abstract';
+import TableDefinition from 'em-table/utils/table-definition';
+import isIOCounter from '../utils/misc';
+
+import CounterColumnDefinition from '../utils/counter-column-definition';
+
+var MoreObject = more.Object;
+
+export default AbstractController.extend({
+  queryParams: ["rowCount", "searchText", "sortColumnId", "sortOrder", "pageNo"],
+  rowCount: 10,
+  searchText: "",
+  sortColumnId: "",
+  sortOrder: "",
+  pageNo: 1,
+
+  columns: [],
+
+  headerComponentNames: ['em-table-search-ui', 'table-controls', 'em-table-pagination-ui'],
+
+  visibleColumnIDs: {},
+  columnSelectorTitle: 'Column Selector',
+  columnSelectorMessage: "",
+
+  definition: Ember.computed(function () {
+    return TableDefinition.create({
+      rowCount: this.get("rowCount"),
+      searchText: this.get("searchText"),
+      sortColumnId: this.get("sortColumnId"),
+      sortOrder: this.get("sortOrder"),
+      pageNo: this.get("pageNo")
+    });
+  }),
+
+  storageID: Ember.computed("name", function () {
+    return this.get("name") + ":visibleColumnIDs";
+  }),
+
+  initVisibleColumns: Ember.on("init", Ember.observer("columns", function () { //To reset on entity change
+    var visibleColumnIDs = this.get("localStorage").get(this.get("storageID")) || {};
+
+    this.get('columns').forEach(function (config) {
+      if(visibleColumnIDs[config.id] !== false) {
+        visibleColumnIDs[config.id] = true;
+      }
+    });
+
+    this.set('visibleColumnIDs', visibleColumnIDs);
+  })),
+
+  allColumns: Ember.computed("columns", function () {
+    var columns = this.get("columns"),
+        counters = this.getCounterColumns();
+
+    return columns.concat(CounterColumnDefinition.make(counters));
+  }),
+
+  visibleColumns: Ember.computed('visibleColumnIDs', 'allColumns', function() {
+    var visibleColumnIDs = this.visibleColumnIDs;
+    return this.get('allColumns').filter(function (column) {
+      return visibleColumnIDs[column.get("id")];
+    });
+  }),
+
+  getCounterColumns: function () {
+    return this.get('env.app.tables.defaultColumns.counters');
+  },
+
+  actions: {
+    searchChanged: function (searchText) {
+      this.set("searchText", searchText);
+    },
+    sortChanged: function (sortColumnId, sortOrder) {
+      this.setProperties({
+        sortColumnId,
+        sortOrder
+      });
+    },
+    rowCountChanged: function (rowCount) {
+      this.set("rowCount", rowCount);
+    },
+    pageChanged: function (pageNum) {
+      this.set("pageNo", pageNum);
+    },
+
+    rowsChanged: function (rows) {
+      this.send("setPollingRecords", rows);
+    },
+
+    // Column selection actions
+    openColumnSelector: function () {
+      this.send("openModal", "column-selector", {
+        title: this.get('columnSelectorTitle'),
+        targetObject: this,
+        content: {
+          message: this.get('columnSelectorMessage'),
+          columns: this.get('allColumns'),
+          visibleColumnIDs: this.get('visibleColumnIDs')
+        }
+      });
+    },
+    columnsSelected: function (visibleColumnIDs) {
+      var columnIDs = {};
+
+      MoreObject.forEach(visibleColumnIDs, function (key, value) {
+        if(!isIOCounter(key)) {
+          columnIDs[key] = value;
+        }
+      });
+
+      if(!MoreObject.equals(columnIDs, this.get("visibleColumnIDs"))) {
+        this.get("localStorage").set(this.get("storageID"), columnIDs);
+        this.set('visibleColumnIDs', columnIDs);
+      }
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/task.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/task.js b/tez-ui2/src/main/webapp/app/controllers/task.js
index 2092162..ffd4ffe 100644
--- a/tez-ui2/src/main/webapp/app/controllers/task.js
+++ b/tez-ui2/src/main/webapp/app/controllers/task.js
@@ -18,12 +18,12 @@
 
 import Ember from 'ember';
 
-import AbstractController from './abstract';
+import ParentController from './parent';
 
-export default AbstractController.extend({
+export default ParentController.extend({
   breadcrumbs: Ember.computed("model.dag", function () {
     var dagName = this.get("model.dag.name"),
-        vertexName = this.get("model.vertexName"),
+        vertexName = this.get("model.vertexName") || this.get("model.vertexIndex"),
         taskIndex = this.get("model.index");
 
     return [{

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/task/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/task/attempts.js b/tez-ui2/src/main/webapp/app/controllers/task/attempts.js
index d7bec55..472d04f 100644
--- a/tez-ui2/src/main/webapp/app/controllers/task/attempts.js
+++ b/tez-ui2/src/main/webapp/app/controllers/task/attempts.js
@@ -16,12 +16,12 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
 import AutoCounterColumn from '../../mixins/auto-counter-column';
 
-export default TablePageController.extend(AutoCounterColumn, {
+export default MultiTableController.extend(AutoCounterColumn, {
   breadcrumbs: [{
     text: "Task Attempts",
     routeName: "task.attempts",
@@ -43,7 +43,8 @@ export default TablePageController.extend(AutoCounterColumn, {
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/task/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/task/counters.js b/tez-ui2/src/main/webapp/app/controllers/task/counters.js
index b9c00e3..4aa071c 100644
--- a/tez-ui2/src/main/webapp/app/controllers/task/counters.js
+++ b/tez-ui2/src/main/webapp/app/controllers/task/counters.js
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import CountersPageController from '../counters-page';
+import CountersTableController from '../counters-table';
 
-export default CountersPageController.extend({
+export default CountersTableController.extend({
   breadcrumbs: [{
     text: "Task Counters",
     routeName: "task.counters",

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/vertex.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/vertex.js b/tez-ui2/src/main/webapp/app/controllers/vertex.js
index 5543924..78f5db9 100644
--- a/tez-ui2/src/main/webapp/app/controllers/vertex.js
+++ b/tez-ui2/src/main/webapp/app/controllers/vertex.js
@@ -18,12 +18,12 @@
 
 import Ember from 'ember';
 
-import AbstractController from './abstract';
+import ParentController from './parent';
 
-export default AbstractController.extend({
+export default ParentController.extend({
   breadcrumbs: Ember.computed("model.dag", function () {
     var dagName = this.get("model.dag.name"),
-        vertexName = this.get("model.name");
+        vertexName = this.get("model.name") || this.get("model.index");
 
     return [{
       text: `DAG [ ${dagName} ]`,

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/vertex/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/vertex/attempts.js b/tez-ui2/src/main/webapp/app/controllers/vertex/attempts.js
index b0fb983..34a067f 100644
--- a/tez-ui2/src/main/webapp/app/controllers/vertex/attempts.js
+++ b/tez-ui2/src/main/webapp/app/controllers/vertex/attempts.js
@@ -16,12 +16,12 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
 import AutoCounterColumn from '../../mixins/auto-counter-column';
 
-export default TablePageController.extend(AutoCounterColumn, {
+export default MultiTableController.extend(AutoCounterColumn, {
   breadcrumbs: [{
     text: "Task Attempts",
     routeName: "vertex.attempts",
@@ -55,7 +55,8 @@ export default TablePageController.extend(AutoCounterColumn, {
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/vertex/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/vertex/counters.js b/tez-ui2/src/main/webapp/app/controllers/vertex/counters.js
index 245ae1b..1213728 100644
--- a/tez-ui2/src/main/webapp/app/controllers/vertex/counters.js
+++ b/tez-ui2/src/main/webapp/app/controllers/vertex/counters.js
@@ -16,9 +16,9 @@
  * limitations under the License.
  */
 
-import CountersPageController from '../counters-page';
+import CountersTableController from '../counters-table';
 
-export default CountersPageController.extend({
+export default CountersTableController.extend({
   breadcrumbs: [{
     text: "Vertex Counters",
     routeName: "vertex.counters",

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/controllers/vertex/tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/controllers/vertex/tasks.js b/tez-ui2/src/main/webapp/app/controllers/vertex/tasks.js
index 350d246..ea02d61 100644
--- a/tez-ui2/src/main/webapp/app/controllers/vertex/tasks.js
+++ b/tez-ui2/src/main/webapp/app/controllers/vertex/tasks.js
@@ -16,12 +16,12 @@
  * limitations under the License.
  */
 
-import TablePageController from '../table-page';
+import MultiTableController from '../multi-table';
 import ColumnDefinition from 'em-table/utils/column-definition';
 
 import AutoCounterColumn from '../../mixins/auto-counter-column';
 
-export default TablePageController.extend(AutoCounterColumn, {
+export default MultiTableController.extend(AutoCounterColumn, {
   breadcrumbs: [{
     text: "Tasks",
     routeName: "vertex.tasks",
@@ -43,7 +43,8 @@ export default TablePageController.extend(AutoCounterColumn, {
     id: 'status',
     headerTitle: 'Status',
     contentPath: 'status',
-    cellComponentName: 'em-table-status-cell'
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
   },{
     id: 'progress',
     headerTitle: 'Progress',

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/entities/am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/entities/am.js b/tez-ui2/src/main/webapp/app/entities/am.js
new file mode 100644
index 0000000..56d061d
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/entities/am.js
@@ -0,0 +1,58 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+import Entity from './entity';
+
+export default Entity.extend({
+
+  idsToJoin: null,
+  deferred: null,
+
+  resetJoiner: Ember.on("init", function () {
+    this.set("idsToJoin", []);
+    this.set("deferred", Ember.RSVP.defer());
+  }),
+
+  queryRecord: function (loader, id, options, query, urlParams) {
+    this.get("idsToJoin").push(query[this.get("queryPropertyToJoin")]);
+
+    // Yup, only the last query would be taken by design
+    Ember.run.once(this, "queryJoinedRecords", loader, options, query, urlParams);
+
+    return this.get("deferred.promise").then(function (recordHash) {
+      return recordHash[id];
+    });
+  },
+
+  queryJoinedRecords: function (loader, options, query, urlParams) {
+    var deferred = this.get("deferred");
+
+    query[this.get("queryPropertyToJoin")] = this.get("idsToJoin").join(",");
+    this.query(loader, query, options, urlParams).then(function (records) {
+      deferred.resolve(records.reduce(function (recordHash, record) {
+        recordHash[record.get("entityID")] = record;
+        return recordHash;
+      }, {}));
+    }, function (error) {
+      deferred.reject(error);
+    }).finally(this.resetJoiner.bind(this));
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/entities/attempt-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/entities/attempt-am.js b/tez-ui2/src/main/webapp/app/entities/attempt-am.js
new file mode 100644
index 0000000..077c494
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/entities/attempt-am.js
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMEntity from './am';
+
+export default AMEntity.extend({
+  queryPropertyToJoin: "attemptID",
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/entities/entity.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/entities/entity.js b/tez-ui2/src/main/webapp/app/entities/entity.js
index 9cad7b7..8a10dee 100644
--- a/tez-ui2/src/main/webapp/app/entities/entity.js
+++ b/tez-ui2/src/main/webapp/app/entities/entity.js
@@ -18,61 +18,133 @@
  */
 
 import Ember from 'ember';
+import NameMixin from '../mixins/name';
 
 var MoreObject = more.Object;
 
-export default Ember.Object.extend({
-
-  loadRelations: function (loader, model, options, urlParams) {
-    var needsPromise = this.loadNeeds(loader, model, options, urlParams);
+var Entity = Ember.Object.extend(NameMixin, {
+
+  queryRecord: function (loader, id, options, query, urlParams) {
+    var that = this;
+    return this.get('store').queryRecord(this.get("name"), {
+      id: id,
+      nameSpace: loader.get('nameSpace'),
+      params: query,
+      urlParams: urlParams
+    }).then(function (record) {
+      return that._loadAllNeeds(loader, record, options, urlParams);
+    });
+  },
 
-    if(needsPromise) {
-      return needsPromise.then(function () {
-        return model;
+  query: function (loader, query, options, urlParams) {
+    var that = this;
+    return this.get('store').query(this.get("name"), {
+      nameSpace: loader.get('nameSpace'),
+      params: query,
+      urlParams: urlParams
+    }).then(function (records) {
+      return Ember.RSVP.all(records.map(function (record) {
+        return that._loadAllNeeds(loader, record, options, urlParams);
+      })).then(function () {
+       return records;
       });
-    }
-
-    return model;
+    });
   },
 
-  normalizeNeed: function(name, options) {
+  normalizeNeed: function(name, needOptions, parentModel, queryParams, urlParams) {
     var need = {
       name: name,
       type: name,
-      idKey: options,
-      lazy: false,
-      silent: false
-    };
+      idKey: needOptions,
+
+      loadType: "", // Possible values lazy, demand
+      silent: false,
+
+      //urlParams
+      //queryParams
+    },
+    overrides = {};
+
+    if(typeof needOptions === 'object') {
+      Ember.assert(`idKey not defined for need '${name}'!`, needOptions.idKey);
+
+      if(MoreObject.isFunction(needOptions.urlParams)) {
+        overrides.urlParams = needOptions.urlParams.call(needOptions, parentModel);
+      }
+      if(MoreObject.isFunction(needOptions.queryParams)) {
+        overrides.queryParams = needOptions.queryParams.call(needOptions, parentModel);
+      }
+
+      overrides = Ember.Object.create({}, needOptions, overrides);
+    }
+
+    if(queryParams) {
+      overrides.queryParams = Ember.$.extend({}, overrides.queryParams, queryParams);
+    }
+    if(urlParams) {
+      overrides.urlParams = Ember.$.extend({}, overrides.urlParams, urlParams);
+    }
+
+    return Ember.Object.create(need, overrides);
+  },
+
+  _loadNeed: function (loader, parentModel, needOptions, options) {
+    var needLoader = loader.queryRecord(
+      needOptions.type,
+      parentModel.get(needOptions.idKey),
+      options,
+      needOptions.queryParams,
+      needOptions.urlParams
+    );
+
+    needLoader.then(function (model) {
+      parentModel.set(needOptions.name, model);
+    });
+
+    if(needOptions.silent) {
+      needLoader = needLoader.catch(function () {
+        parentModel.set(needOptions.name, null);
+      });
+    }
+
+    return needLoader;
+  },
+
+  loadNeed: function (loader, parentModel, needName, options, queryParams, urlParams) {
+    var needOptions = parentModel.get(`needs.${needName}`);
+    Ember.assert(`Need '${needName}' not defined in model!`, needOptions);
+
+    needOptions = this.normalizeNeed(needName, needOptions, parentModel, queryParams, urlParams);
+    return this._loadNeed(loader, parentModel, needOptions, options);
+  },
 
-    if(typeof options === 'object') {
-      return Ember.Object.create(need, options);
+  _loadAllNeeds: function (loader, model, options/*, urlParams*/) {
+    var needsPromise = this.loadAllNeeds(loader, model, options);
+
+    if(needsPromise) {
+      return needsPromise.then(function () {
+        return model;
+      });
     }
 
-    return Ember.Object.create(need);
+    return model;
   },
 
-  loadNeeds: function (loader, parentModel, options, urlParams) {
+  loadAllNeeds: function (loader, parentModel, options, queryParams, urlParams) {
     var needLoaders = [],
         that = this,
         needs = parentModel.get("needs");
 
     if(needs) {
       MoreObject.forEach(needs, function (name, needOptions) {
-        var need = that.normalizeNeed(name, needOptions),
-            needLoader = loader.queryRecord(need.type, parentModel.get(need.idKey), null, options, urlParams);
-
-        needLoader.then(function (model) {
-          parentModel.set(need.name, model);
-        });
+        needOptions = that.normalizeNeed(name, needOptions, parentModel, queryParams, urlParams);
 
-        if(need.silent) {
-          needLoader = needLoader.catch(function () {
-            parentModel.set(need.name, null);
-          });
-        }
+        if(needOptions.loadType !== "demand") {
+          let needLoader = that._loadNeed(loader, parentModel, needOptions, options);
 
-        if(!need.lazy) {
-          needLoaders.push(needLoader);
+          if(needOptions.loadType !== "lazy") {
+            needLoaders.push(needLoader);
+          }
         }
       });
     }
@@ -83,3 +155,5 @@ export default Ember.Object.extend({
   },
 
 });
+
+export default Entity;

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/entities/task-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/entities/task-am.js b/tez-ui2/src/main/webapp/app/entities/task-am.js
new file mode 100644
index 0000000..0e41239
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/entities/task-am.js
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMEntity from './am';
+
+export default AMEntity.extend({
+  queryPropertyToJoin: "taskID",
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/entities/vertex-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/entities/vertex-am.js b/tez-ui2/src/main/webapp/app/entities/vertex-am.js
new file mode 100644
index 0000000..15a26da
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/entities/vertex-am.js
@@ -0,0 +1,23 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMEntity from './am';
+
+export default AMEntity.extend({
+  queryPropertyToJoin: "vertexID",
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/initializers/entities.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/initializers/entities.js b/tez-ui2/src/main/webapp/app/initializers/entities.js
index 86d796c..b5afd31 100644
--- a/tez-ui2/src/main/webapp/app/initializers/entities.js
+++ b/tez-ui2/src/main/webapp/app/initializers/entities.js
@@ -20,6 +20,7 @@ import registerWithContainer from "ember-cli-auto-register/register";
 
 export function initialize(application) {
   registerWithContainer("entity", application);
+  application.inject('entitie', 'store', 'service:store');
 }
 
 export default {

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/mixins/auto-counter-column.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/mixins/auto-counter-column.js b/tez-ui2/src/main/webapp/app/mixins/auto-counter-column.js
index 7820e4a..0504d4b 100644
--- a/tez-ui2/src/main/webapp/app/mixins/auto-counter-column.js
+++ b/tez-ui2/src/main/webapp/app/mixins/auto-counter-column.js
@@ -39,16 +39,16 @@ export default Ember.Mixin.create({
 
     if(records) {
       records.forEach(function (record) {
-        let counterGroups = Ember.get(record, 'counterGroups');
+        let counterGroupsHash = Ember.get(record, 'counterGroupsHash');
 
-        if(counterGroups) {
-          counterGroups.forEach(function (group) {
+        if(counterGroupsHash) {
+          MoreObject.forEach(counterGroupsHash, function (groupName, countersHash) {
             var groupHash =
-                counterHash[group.counterGroupName] =
-                counterHash[group.counterGroupName] || {};
+                counterHash[groupName] =
+                counterHash[groupName] || {};
 
-            group.counters.forEach(function (counter) {
-              groupHash[counter.counterName] = counter.counterName;
+            MoreObject.forEach(countersHash, function (counterName) {
+              groupHash[counterName] = counterName;
             });
           });
         }

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/abstract.js b/tez-ui2/src/main/webapp/app/models/abstract.js
index cf6ea8a..24bcbd3 100644
--- a/tez-ui2/src/main/webapp/app/models/abstract.js
+++ b/tez-ui2/src/main/webapp/app/models/abstract.js
@@ -16,6 +16,7 @@
  * limitations under the License.
  */
 
+import Ember from 'ember';
 import DS from 'ember-data';
 
 export default DS.Model.extend({
@@ -36,4 +37,24 @@ export default DS.Model.extend({
   didLoad: function () {
     this.refreshLoadTime();
   },
+
+  entityID: DS.attr("string"),
+
+  index: Ember.computed("entityID", function () {
+    var id = this.get("entityID") || "";
+    return id.substr(id.lastIndexOf('_') + 1);
+  }),
+
+  status: DS.attr("string"),
+  isComplete: Ember.computed("status", function () {
+    switch(this.get("status")) {
+      case "SUCCEEDED":
+      case "FINISHED":
+      case "FAILED":
+      case "KILLED":
+        return true;
+    }
+    return false;
+  }),
+
 });

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/ahs-app.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/ahs-app.js b/tez-ui2/src/main/webapp/app/models/ahs-app.js
index ce087eb31..c18bed9 100644
--- a/tez-ui2/src/main/webapp/app/models/ahs-app.js
+++ b/tez-ui2/src/main/webapp/app/models/ahs-app.js
@@ -22,8 +22,6 @@ import DS from 'ember-data';
 import AbstractModel from './abstract';
 
 export default AbstractModel.extend({
-  entityID: DS.attr('string'),
-
   attemptID: DS.attr('string'),
 
   name: DS.attr('string'),

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/am-timeline.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/am-timeline.js b/tez-ui2/src/main/webapp/app/models/am-timeline.js
new file mode 100644
index 0000000..bfd03b3
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/am-timeline.js
@@ -0,0 +1,46 @@
+/*global more*/
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+import DS from 'ember-data';
+
+import TimelineModel from './timeline';
+
+var MoreObject = more.Object;
+
+// For all AM related entities that can be updated from AM
+export default TimelineModel.extend({
+
+  am: DS.attr("object"), // Represents data from am
+
+  status: Ember.computed("am.status", "atsStatus", "app.status", "app.finalStatus", function () {
+    return this.get("am.status") || this._super();
+  }),
+
+  progress: Ember.computed("am.progress", "status", function () {
+    var progress = this.get("am.progress");
+    return MoreObject.isNumber(progress) ? progress : this._super();
+  }),
+
+  counterGroupsHash: Ember.computed("am.counterGroupsHash", "_counterGroups", function () {
+    var amCounters = this.get("am.counterGroupsHash"),
+        atsCounters = this._super();
+    return amCounters ? Ember.$.extend({}, atsCounters, amCounters) : atsCounters;
+  })
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/am.js b/tez-ui2/src/main/webapp/app/models/am.js
new file mode 100644
index 0000000..46ec75e
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/am.js
@@ -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.
+ */
+
+import DS from 'ember-data';
+
+import AbstractModel from './abstract';
+
+export default AbstractModel.extend({
+
+  entityID: DS.attr("string"),
+
+  status: DS.attr("string"),
+  progress: DS.attr("number"),
+
+  counterGroupsHash: DS.attr("object")
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/app-rm.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/app-rm.js b/tez-ui2/src/main/webapp/app/models/app-rm.js
new file mode 100644
index 0000000..34bf6b3
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/app-rm.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import RMModel from './rm';
+
+export default RMModel.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/app.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/app.js b/tez-ui2/src/main/webapp/app/models/app.js
index 82ffffc..6dcedd1 100644
--- a/tez-ui2/src/main/webapp/app/models/app.js
+++ b/tez-ui2/src/main/webapp/app/models/app.js
@@ -20,22 +20,6 @@ import Ember from 'ember';
 import DS from 'ember-data';
 
 import TimelineModel from './timeline';
-/*
-  Inherited properties
-
-  entityID - String
-  appID - Computed from entityID
-
-  status - String
-  progress - Computed from status
-
-  startTime - Number
-  endTime - Number
-  duration - Computed from start & end times
-
-  counterGroups - Array
-  counterHash - Computed from counterGroups
-*/
 
 export default TimelineModel.extend({
   appID: Ember.computed("entityID", function () {

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/attempt-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/attempt-am.js b/tez-ui2/src/main/webapp/app/models/attempt-am.js
new file mode 100644
index 0000000..55722b6
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/attempt-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMModel from './am';
+
+export default AMModel.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/attempt.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/attempt.js b/tez-ui2/src/main/webapp/app/models/attempt.js
index eb99169..5f865a0 100644
--- a/tez-ui2/src/main/webapp/app/models/attempt.js
+++ b/tez-ui2/src/main/webapp/app/models/attempt.js
@@ -19,45 +19,48 @@
 import Ember from 'ember';
 import DS from 'ember-data';
 
-import TimelineModel from './timeline';
-/*
-  Inherited properties
+import AMTimelineModel from './am-timeline';
 
-  entityID - String
-  appID - Computed from entityID
-
-  status - String
-  progress - Computed from status
-
-  startTime - Number
-  endTime - Number
-  duration - Computed from start & end times
-
-  counterGroups - Array
-  counterHash - Computed from counterGroups
-*/
-
-export default TimelineModel.extend({
+export default AMTimelineModel.extend({
   needs: {
     dag: {
       type: "dag",
       idKey: "dagID",
       silent: true
+    },
+    am: {
+      type: "attemptAm",
+      idKey: "entityID",
+      loadType: "demand",
+      queryParams: function (model) {
+        var vertexIndex = parseInt(model.get("vertexIndex")),
+            taskIndex = parseInt(model.get("taskIndex")),
+            attemptIndex = parseInt(model.get("index"));
+        return {
+          attemptID: `${vertexIndex}_${taskIndex}_${attemptIndex}`,
+          dagID: parseInt(model.get("dag.index")),
+          counters: "*"
+        };
+      },
+      urlParams: function (model) {
+        return {
+          app_id: model.get("appID")
+        };
+      }
     }
   },
 
-  index: Ember.computed("entityID", function () {
-    var idParts = this.get("entityID").split("_");
-    return idParts[Math.max(idParts.length - 1, 1)];
-  }),
-
   taskID: DS.attr('string'),
   taskIndex: Ember.computed("taskID", function () {
-    var idParts = this.get("taskID").split("_");
-    return idParts.slice(Math.max(idParts.length - 2, 1)).join("_");
+    var id = this.get("taskID") || "";
+    return id.substr(id.lastIndexOf('_') + 1);
   }),
 
   vertexID: DS.attr('string'),
+  vertexIndex: Ember.computed("vertexID", function () {
+    var id = this.get("vertexID") || "";
+    return id.substr(id.lastIndexOf('_') + 1);
+  }),
   vertexName: Ember.computed("vertexID", "dag", function () {
     var vertexID = this.get("vertexID");
     return this.get(`dag.vertexIdNameMap.${vertexID}`);

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/dag-am.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/dag-am.js b/tez-ui2/src/main/webapp/app/models/dag-am.js
new file mode 100644
index 0000000..55722b6
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/dag-am.js
@@ -0,0 +1,22 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AMModel from './am';
+
+export default AMModel.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/dag.js b/tez-ui2/src/main/webapp/app/models/dag.js
index e0a4b55..bb4c5df 100644
--- a/tez-ui2/src/main/webapp/app/models/dag.js
+++ b/tez-ui2/src/main/webapp/app/models/dag.js
@@ -19,25 +19,28 @@
 import Ember from 'ember';
 import DS from 'ember-data';
 
-import TimelineModel from './timeline';
-/*
-  Inherited properties
+import AMTimelineModel from './am-timeline';
+
+export default AMTimelineModel.extend({
+  needs: {
+    am: {
+      type: "dagAm",
+      idKey: "entityID",
+      loadType: "demand",
+      queryParams: function (model) {
+        return {
+          dagID: parseInt(model.get("index")),
+          counters: "*"
+        };
+      },
+      urlParams: function (model) {
+        return {
+          app_id: model.get("appID")
+        };
+      }
+    }
+  },
 
-  entityID - String
-  appID - Computed from entityID
-
-  status - String
-  progress - Computed from status
-
-  startTime - Number
-  endTime - Number
-  duration - Computed from start & end times
-
-  counterGroups - Array
-  counterHash - Computed from counterGroups
-*/
-
-export default TimelineModel.extend({
   name: DS.attr("string"),
 
   submitter: DS.attr("string"),

http://git-wip-us.apache.org/repos/asf/tez/blob/6f366403/tez-ui2/src/main/webapp/app/models/rm.js
----------------------------------------------------------------------
diff --git a/tez-ui2/src/main/webapp/app/models/rm.js b/tez-ui2/src/main/webapp/app/models/rm.js
new file mode 100644
index 0000000..d35ba23
--- /dev/null
+++ b/tez-ui2/src/main/webapp/app/models/rm.js
@@ -0,0 +1,26 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import DS from 'ember-data';
+
+import AbstractModel from './abstract';
+
+export default AbstractModel.extend({
+  entityID: DS.attr("string"),
+  status: DS.attr("string"),
+});