YARN-5705. Show timeline data from ATS v2 in new web UI. Contributed by Akhil 
PB.


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

Branch: refs/heads/trunk
Commit: 46d9c4ca7aba04e96bea65d7b95cc84b50af6980
Parents: c80d3bc
Author: Sunil G <sun...@apache.org>
Authored: Sun May 21 18:09:13 2017 +0530
Committer: Sunil G <sun...@apache.org>
Committed: Sun May 21 18:09:13 2017 +0530

----------------------------------------------------------------------
 .../webapp/app/adapters/yarn-app-attempt.js     |   4 +-
 .../webapp/app/adapters/yarn-app-flowrun.js     |  33 +++
 .../webapp/app/adapters/yarn-app-timeline.js    |  35 +++
 .../main/webapp/app/adapters/yarn-container.js  |  18 +-
 .../src/main/webapp/app/adapters/yarn-entity.js |  35 +++
 .../webapp/app/adapters/yarn-flow-activity.js   |  30 +++
 .../webapp/app/adapters/yarn-flowrun-brief.js   |  32 +++
 .../main/webapp/app/adapters/yarn-flowrun.js    |  38 +++
 .../app/adapters/yarn-timeline-appattempt.js    |  41 +++
 .../app/adapters/yarn-timeline-container.js     |  40 +++
 .../main/webapp/app/components/nodes-heatmap.js |  18 +-
 .../webapp/app/components/simple-bar-chart.js   | 206 +++++++++++++++
 .../webapp/app/components/sunburst-chart.js     | 261 +++++++++++++++++++
 .../webapp/app/controllers/yarn-apps/apps.js    |   1 -
 .../app/controllers/yarn-apps/services.js       |   1 -
 .../app/controllers/yarn-flow-activity.js       | 125 +++++++++
 .../main/webapp/app/controllers/yarn-flow.js    |  36 +++
 .../webapp/app/controllers/yarn-flow/info.js    |  66 +++++
 .../webapp/app/controllers/yarn-flow/runs.js    | 178 +++++++++++++
 .../main/webapp/app/controllers/yarn-flowrun.js |  50 ++++
 .../webapp/app/controllers/yarn-flowrun/info.js | 157 +++++++++++
 .../app/controllers/yarn-flowrun/metrics.js     | 126 +++++++++
 .../webapp/app/controllers/yarn-services.js     |  12 +-
 .../src/main/webapp/app/mixins/app-attempt.js   |  66 +++++
 .../main/webapp/app/models/yarn-app-attempt.js  |  11 +-
 .../main/webapp/app/models/yarn-app-flowrun.js  |  52 ++++
 .../main/webapp/app/models/yarn-app-timeline.js | 105 ++++++++
 .../main/webapp/app/models/yarn-container.js    |   9 +-
 .../src/main/webapp/app/models/yarn-entity.js   |  26 ++
 .../webapp/app/models/yarn-flow-activity.js     |  28 ++
 .../webapp/app/models/yarn-flowrun-brief.js     |  70 +++++
 .../src/main/webapp/app/models/yarn-flowrun.js  |  32 +++
 .../app/models/yarn-timeline-appattempt.js      | 143 ++++++++++
 .../app/models/yarn-timeline-container.js       |  63 +++++
 .../src/main/webapp/app/router.js               |  12 +
 .../main/webapp/app/routes/timeline-error.js    |  29 +++
 .../main/webapp/app/routes/yarn-app-attempt.js  |  32 +--
 .../main/webapp/app/routes/yarn-app-attempts.js |  13 +-
 .../src/main/webapp/app/routes/yarn-app.js      |  18 +-
 .../webapp/app/routes/yarn-flow-activity.js     |  37 +++
 .../src/main/webapp/app/routes/yarn-flow.js     |  53 ++++
 .../main/webapp/app/routes/yarn-flow/info.js    |  22 ++
 .../main/webapp/app/routes/yarn-flow/runs.js    |  22 ++
 .../webapp/app/routes/yarn-flowrun-metric.js    | 107 ++++++++
 .../src/main/webapp/app/routes/yarn-flowrun.js  |  58 +++++
 .../main/webapp/app/routes/yarn-flowrun/info.js |  22 ++
 .../webapp/app/routes/yarn-flowrun/metrics.js   |  22 ++
 .../webapp/app/serializers/yarn-app-flowrun.js  |  64 +++++
 .../webapp/app/serializers/yarn-app-timeline.js |  76 ++++++
 .../src/main/webapp/app/serializers/yarn-app.js |   3 +-
 .../main/webapp/app/serializers/yarn-entity.js  |  51 ++++
 .../app/serializers/yarn-flow-activity.js       |  54 ++++
 .../app/serializers/yarn-flowrun-brief.js       |  64 +++++
 .../main/webapp/app/serializers/yarn-flowrun.js |  63 +++++
 .../main/webapp/app/serializers/yarn-queue.js   |  22 +-
 .../app/serializers/yarn-timeline-appattempt.js |  69 +++++
 .../app/serializers/yarn-timeline-container.js  |  71 +++++
 .../src/main/webapp/app/styles/app.css          |  83 ++++++
 .../main/webapp/app/templates/application.hbs   |   6 +-
 .../webapp/app/templates/timeline-error.hbs     |  22 ++
 .../webapp/app/templates/yarn-app-attempt.hbs   |  46 ++--
 .../webapp/app/templates/yarn-app-attempts.hbs  |   7 +-
 .../src/main/webapp/app/templates/yarn-app.hbs  |  51 +---
 .../src/main/webapp/app/templates/yarn-apps.hbs |   4 +-
 .../webapp/app/templates/yarn-flow-activity.hbs |  45 ++++
 .../src/main/webapp/app/templates/yarn-flow.hbs |  49 ++++
 .../webapp/app/templates/yarn-flow/info.hbs     |  53 ++++
 .../webapp/app/templates/yarn-flow/runs.hbs     | 131 ++++++++++
 .../app/templates/yarn-flowrun-metric.hbs       |  34 +++
 .../main/webapp/app/templates/yarn-flowrun.hbs  |  49 ++++
 .../webapp/app/templates/yarn-flowrun/info.hbs  | 128 +++++++++
 .../app/templates/yarn-flowrun/metrics.hbs      |  34 +++
 .../main/webapp/app/templates/yarn-services.hbs |   2 +-
 .../src/main/webapp/app/utils/converter.js      |  22 +-
 .../src/main/webapp/app/utils/error-utils.js    |  58 +++++
 .../src/main/webapp/config/default-config.js    |   3 +-
 .../hadoop-yarn-ui/src/main/webapp/package.json |   1 +
 .../components/simple-bar-chart-test.js         |  43 +++
 .../unit/adapters/yarn-app-timeline-test.js     |  30 +++
 .../adapters/yarn-timeline-appattempt-test.js   |  30 +++
 .../adapters/yarn-timeline-container-test.js    |  30 +++
 .../unit/controllers/yarn-flow/info-test.js     |  30 +++
 .../unit/controllers/yarn-flow/runs-test.js     |  30 +++
 .../unit/controllers/yarn-flowrun/info-test.js  |  30 +++
 .../controllers/yarn-flowrun/metrics-test.js    |  30 +++
 .../tests/unit/mixins/app-attempt-test.js       |  30 +++
 .../webapp/tests/unit/mixins/charts-test.js     |  30 ---
 .../tests/unit/models/yarn-app-timeline-test.js |  30 +++
 .../models/yarn-timeline-appattempt-test.js     |  30 +++
 .../unit/models/yarn-timeline-container-test.js |  30 +++
 .../tests/unit/routes/timeline-error-test.js    |  29 +++
 .../tests/unit/routes/yarn-flow/info-test.js    |  29 +++
 .../tests/unit/routes/yarn-flow/runs-test.js    |  29 +++
 .../tests/unit/routes/yarn-flowrun/info-test.js |  29 +++
 .../unit/routes/yarn-flowrun/metrics-test.js    |  29 +++
 .../unit/serializers/yarn-app-timeline-test.js  |  33 +++
 .../yarn-timeline-appattempt-test.js            |  33 +++
 .../serializers/yarn-timeline-container-test.js |  33 +++
 98 files changed, 4408 insertions(+), 199 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js
index 2389f16..d5f3d0c 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-attempt.js
@@ -26,7 +26,9 @@ export default AbstractAdapter.extend({
 
   urlForQuery(query/*, modelName*/) {
     var url = this._buildURL();
-    return url + '/apps/' + query.appId + "/appattempts";
+    var appId = query.appId;
+    delete query.appId;
+    return url + '/apps/' + appId + "/appattempts";
   },
 
   urlForFindRecord(id/*, modelName, snapshot*/) {

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js
new file mode 100644
index 0000000..23ecd1b
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-flowrun.js
@@ -0,0 +1,33 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/){
+    var url = this._buildURL();
+    var flowrunUid = query['flowrunUid'];
+    delete query.flowrunUid;
+    url = url + '/run-uid/' + flowrunUid + '/apps?fields=ALL';
+    return url;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js
new file mode 100644
index 0000000..831649c
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-app-timeline.js
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForFindRecord(id/*, modelName, snapshot*/) {
+    var url = this._buildURL();
+    url = url + '/apps/' + id + '?fields=ALL';
+    return url;
+  },
+
+  pathForType(/*modelName*/) {
+    return 'apps';
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js
index 348a805..476c9be 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-container.js
@@ -25,31 +25,17 @@ export default DS.JSONAPIAdapter.extend({
   },
 
   host: function() {
-    return undefined;
+    return this.get(`hosts.rmWebAddress`);
   }.property(),
 
   namespace: function() {
-    return undefined;
+    return this.get(`env.app.namespaces.cluster`);
   }.property(),
 
   urlForQuery(query/*, modelName*/) {
-    var rmHosts = this.get(`hosts.rmWebAddress`);
-    var tsHosts = this.get(`hosts.timelineWebAddress`);
-    var rmNamespaces = this.get(`env.app.namespaces.cluster`);
-    var tsNamespaces = this.get(`env.app.namespaces.timeline`);
-
-    if (query.is_rm) {
-      this.set("host", rmHosts);
-      this.set("namespace", rmNamespaces);
-    } else {
-      this.set("host", tsHosts);
-      this.set("namespace", tsNamespaces);
-    }
-
     var url = this._buildURL();
     url = url + '/apps/' + Converter.attemptIdToAppId(query.app_attempt_id) +
           "/appattempts/" + query.app_attempt_id + "/containers";
-    console.log(url);
     return url;
   },
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js
new file mode 100644
index 0000000..3d7338f
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-entity.js
@@ -0,0 +1,35 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/){
+    var url = this._buildURL();
+    var appUid = query.app_uid;
+    var entityType = query.entity_type;
+    delete query.app_uid;
+    delete query.entity_type;
+    url = url + '/app-uid/' + appUid + '/entities/' + entityType + 
'?fields=INFO';
+    return url;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.js
new file mode 100644
index 0000000..a8c436a
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flow-activity.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 AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  pathForType(/*modelName*/) {
+    return 'flows'; // move to some common place, return path by modelname.
+  },
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js
new file mode 100644
index 0000000..ea9c6cb
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun-brief.js
@@ -0,0 +1,32 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/){
+    var url = this._buildURL();
+    var flowuid = query['flowuid'];
+    delete query.flowuid;
+    return url + '/flow-uid/' + flowuid + '/runs?fields=ALL';
+  },
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js
new file mode 100644
index 0000000..9163c83
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-flowrun.js
@@ -0,0 +1,38 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQueryRecord(query/*, modelName*/){
+    var url = this._buildURL();
+    var flowrunuid = query.flowrun_uid;
+    delete query.flowrun_uid;
+    url = url + '/run-uid/' + flowrunuid;
+    return url;
+  },
+
+  pathForType(/*modelName*/) {
+    return 'run-uid'; // move to some common place, return path by modelname.
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js
new file mode 100644
index 0000000..2557a86
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-appattempt.js
@@ -0,0 +1,41 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+import Converter from 'yarn-ui/utils/converter';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/) {
+    var url = this._buildURL();
+    var appId = query.appId;
+    query.fields = 'ALL';
+    delete query.appId;
+    return url + '/apps/' + appId + "/entities/YARN_APPLICATION_ATTEMPT";
+  },
+
+  urlForFindRecord(id/*, modelName, snapshot*/) {
+    var url = this._buildURL();
+    return url + '/apps/' + Converter.attemptIdToAppId(id) +
+      "/entities/YARN_APPLICATION_ATTEMPT/" + id + "?fields=ALL";
+  }
+
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js
new file mode 100644
index 0000000..f47335a
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/adapters/yarn-timeline-container.js
@@ -0,0 +1,40 @@
+/**
+ * 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 AbstractAdapter from './abstract';
+import Converter from 'yarn-ui/utils/converter';
+
+export default AbstractAdapter.extend({
+  address: "timelineWebAddress",
+  restNameSpace: "timelineV2",
+  serverName: "ATS",
+
+  urlForQuery(query/*, modelName*/){
+    var url = this._buildURL();
+    var app_attempt_id = query.app_attempt_id;
+    query.fields = 'ALL';
+    delete query.app_attempt_id;
+    url = url + '/apps/' + Converter.attemptIdToAppId(app_attempt_id) +
+        '/entities/YARN_CONTAINER';
+    return url;
+  },
+
+  pathForType(/*modelName*/) {
+    return '';
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js
index ef6e46e..3acc5de 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/nodes-heatmap.js
@@ -52,7 +52,7 @@ export default BaseChartComponent.extend({
 
   bindSelectCategory: function(element, i) {
     element.on("click", function() {
-      if (this.selectedCategory == i) {
+      if (this.selectedCategory === i) {
         // Remove selection for second click
         this.selectedCategory = 0;
       } else {
@@ -76,7 +76,7 @@ export default BaseChartComponent.extend({
     }
 
     var usage = node.get("usedMemoryMB") /
-      (node.get("usedMemoryMB") + node.get("availMemoryMB"))
+      (node.get("usedMemoryMB") + node.get("availMemoryMB"));
     var lowerLimit = (this.selectedCategory - 1) * 0.2;
     var upperLimit = this.selectedCategory * 0.2;
     if (lowerLimit <= usage && usage <= upperLimit) {
@@ -116,6 +116,7 @@ export default BaseChartComponent.extend({
     var sampleXOffset = (layout.x2 - layout.x1) / 2 - 2.5 * 
this.SAMPLE_CELL_WIDTH -
       2 * this.CELL_MARGIN;
     var sampleYOffset = layout.margin * 2;
+    var text;
 
     for (i = 1; i <= 5; i++) {
       var ratio = i * 0.2 - 0.1;
@@ -128,7 +129,7 @@ export default BaseChartComponent.extend({
         .attr("height", this.SAMPLE_HEIGHT)
         .attr("class", "hyperlink");
       this.bindSelectCategory(rect, i);
-      var text = g.append("text")
+      text = g.append("text")
         .text("" + (ratio * 100).toFixed(1) + "% Used")
         .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5)
         .attr("x", sampleXOffset + this.SAMPLE_CELL_WIDTH / 2)
@@ -137,8 +138,8 @@ export default BaseChartComponent.extend({
       sampleXOffset += this.CELL_MARGIN + this.SAMPLE_CELL_WIDTH;
     }
 
-    if (this.selectedCategory != 0) {
-      var text = g.append("text")
+    if (this.selectedCategory !== 0) {
+      text = g.append("text")
         .text("Clear")
         .attr("y", sampleYOffset + this.SAMPLE_HEIGHT / 2 + 5)
         .attr("x", sampleXOffset + 20)
@@ -149,7 +150,7 @@ export default BaseChartComponent.extend({
     var chartXOffset = -1;
 
     for (i = 0; i < racksArray.length; i++) {
-      var text = g.append("text")
+      text = g.append("text")
         .text(racksArray[i])
         .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5)
         .attr("x", layout.margin)
@@ -163,7 +164,6 @@ export default BaseChartComponent.extend({
 
       for (var j = 0; j < data.length; j++) {
         var rack = data[j].get("rack");
-        var host = data[j].get("nodeHostName");
 
         if (rack === racksArray[i]) {
           this.addNode(g, xOffset, yOffset, colorFunc, data[j]);
@@ -217,11 +217,11 @@ export default BaseChartComponent.extend({
         href = `#/yarn-node/${node_id}/${node_addr}`;
     var a = g.append("a")
       .attr("href", href);
-    var text = a.append("text")
+    a.append("text")
       .text(data.get("nodeHostName"))
       .attr("y", yOffset + this.CELL_HEIGHT / 2 + 5)
       .attr("x", xOffset + this.CELL_WIDTH / 2)
-      .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : 
"heatmap-cell-notselected")
+      .attr("class", this.isNodeSelected(data) ? "heatmap-cell" : 
"heatmap-cell-notselected");
     if (this.isNodeSelected(data)) {
       this.bindTP(a, rect);
     }

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js
new file mode 100644
index 0000000..8527e91
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/simple-bar-chart.js
@@ -0,0 +1,206 @@
+/**
+ * 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';
+
+export default Ember.Component.extend({
+  data: [],
+  xAxisTickFormatter: null,
+  yAxisTickFormatter: null,
+  xAxisText: '',
+  yAxisText: '',
+  enableTooltip: true,
+  onBarChartClickCallback: Ember.K,
+  hideTootlipOnBarChartClick: true,
+
+  initChart() {
+    this.height = 400;
+    this.barWidth = 30;
+    this.width = Math.max(500, 40 * this.data.length);
+  },
+
+  drawChart() {
+    var margin = {top: 20, right: 20, bottom: 100, left: 100},
+        axisLabelPadding = 10,
+        width = this.width - margin.left - margin.right - axisLabelPadding,
+        height = this.height - margin.top - margin.bottom - axisLabelPadding,
+        xAxisText = this.xAxisText? this.xAxisText : '',
+        yAxisText = this.yAxisText? this.yAxisText : '',
+        data = this.data,
+        self = this;
+
+    var xScale = d3.scale.ordinal().rangeRoundBands([0, width], 0.1);
+    var yScale = d3.scale.linear().range([height, 0]);
+
+    var xAxis = d3.svg.axis()
+        .scale(xScale)
+        .orient("bottom")
+        .tickFormat(function(tick) {
+          if (self.isFunction(self.xAxisTickFormatter)) {
+            return self.xAxisTickFormatter(tick);
+          } else {
+            return tick;
+          }
+        });
+
+    var yAxis = d3.svg.axis()
+        .scale(yScale)
+        .orient("left")
+        .tickFormat(function(tick) {
+          if (self.isFunction(self.yAxisTickFormatter)) {
+            return self.yAxisTickFormatter(tick);
+          } else {
+            return tick;
+          }
+        });
+
+    var svg = d3.select(this.element)
+      .append("svg")
+        .attr("class", "simple-bar-chart")
+        .attr("width", width + margin.left + margin.right + axisLabelPadding)
+        .attr("height", height + margin.top + margin.bottom + axisLabelPadding)
+      .append("g")
+        .attr("transform", 
"translate("+(margin.left+axisLabelPadding)+","+(margin.top)+")");
+
+    xScale.domain(data.map(function(d) { return d.label; }));
+    yScale.domain([0, d3.max(data, function(d) { return d.value; })]);
+
+    var gx = svg.append("g")
+        .attr("class", "x axis")
+        .attr("transform", "translate(0," + height + ")")
+        .call(xAxis);
+
+    gx.selectAll("text")
+        .style("text-anchor", "end")
+        .attr("dx", "-.8em")
+        .attr("dy", "-.3em")
+        .attr("transform", "rotate(-60)");
+
+    gx.append("text")
+        .attr("transform", "translate("+(width/2)+","+(margin.bottom)+")")
+        .style("text-anchor", "middle")
+        .text(xAxisText);
+
+    var gy = svg.append("g")
+        .attr("class", "y axis")
+        .call(yAxis);
+
+    gy.append("text")
+        .attr("transform", 
"translate("+(-margin.left)+","+(height/2)+")rotate(-90)")
+        .style("text-anchor", "middle")
+        .text(yAxisText);
+
+    var barWidth = this.barWidth;
+    var minBarWidth = Math.min(barWidth, xScale.rangeBand());
+    var bars = svg.selectAll("bar")
+        .data(data)
+      .enter().append("rect")
+        .attr("x", function(d) {
+          var padding = 0;
+          var rangeBand = xScale.rangeBand();
+          if ((rangeBand - barWidth) > 0) {
+            padding = (rangeBand - barWidth) / 2;
+          }
+          return xScale(d.label) + padding;
+        })
+        .attr("width", minBarWidth)
+        .attr("y", function() {
+          return yScale(0);
+        })
+        .attr("height", function() {
+          return height - yScale(0);
+        })
+        .on('click', function(d) {
+          if (self.enableTooltip && self.hideTootlipOnBarChartClick) {
+            self.hideTootlip();
+          }
+          if (self.isFunction(self.onBarChartClickCallback)) {
+            self.onBarChartClickCallback(d);
+          }
+        });
+
+    bars.transition()
+        .duration(1000)
+        .delay(100)
+        .attr("y", function(d) {
+          return yScale(d.value);
+        })
+        .attr("height", function(d) {
+          return height - yScale(d.value);
+        });
+
+    if (this.enableTooltip) {
+      this.bindTooltip(bars);
+    }
+  },
+
+  bindTooltip(bars) {
+    var self = this;
+    var tooltip = this.tooltip;
+    if (tooltip) {
+      bars.on("mouseenter", function(d) {
+        tooltip.html(d.tooltip);
+        self.showTooltip();
+      }).on("mousemove", function() {
+        tooltip.style("left", (d3.event.pageX + 5) + "px")
+            .style("top", (d3.event.pageY - 25) + "px");
+      }).on("mouseout", function() {
+        self.hideTootlip();
+      });
+    }
+  },
+
+  initTooltip() {
+    this.tooltip = d3.select("body")
+        .append("div")
+        .attr("class", "tooltip simple-barchart-tooltip")
+        .style("opacity", 1);
+
+    this.hideTootlip();
+  },
+
+  hideTootlip() {
+    if (this.tooltip) {
+     this.tooltip.style("display", "none");
+    }
+  },
+
+  showTooltip() {
+    if (this.tooltip) {
+     this.tooltip.style("display", "block");
+    }
+  },
+
+  isFunction(func) {
+    return Ember.typeOf(func) === "function";
+  },
+
+  didInsertElement() {
+    this.initChart();
+    if (this.enableTooltip) {
+      this.initTooltip();
+    }
+    this.drawChart();
+  },
+
+  willDestroyElement() {
+    if (this.tooltip) {
+      this.tooltip.remove();
+    }
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js
new file mode 100644
index 0000000..3a2302a
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/components/sunburst-chart.js
@@ -0,0 +1,261 @@
+/**
+ * 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';
+
+export default Ember.Component.extend({
+
+  didInsertElement: function() {
+    var json = buildHierarchy(this.get("arr"));
+    createVisualization(json);
+  },
+
+});
+// Dimensions of sunburst.
+var  width = 1000;
+var  height = 750;
+var  radius = Math.min(width, height) / 2;
+// Breadcrumb dimensions: width, height, spacing, width of tip/tail.
+var  b = { w: 225, h: 30, s: 3, t: 10 };
+// Total size of all segments; we set this later, after loading the data.
+var totalSize = 0;
+var vis = null;
+var  partition = null;
+var  arc = null;
+var colors = d3.scale.category20c();
+
+function colorMap(d) {
+  return colors(d.name);
+}
+
+// Given a node in a partition layout, return an array of all of its ancestor
+// nodes, highest first, but excluding the root.
+function  getAncestors(node) {
+  var path = [];
+  var current = node;
+  while (current.parent) {
+    path.unshift(current);
+    current = current.parent;
+  }
+  return path;
+}
+
+// Main function to draw and set up the visualization, once we have the data.
+function createVisualization(json) {
+  partition = d3.layout.partition()
+      .size([2 * Math.PI, radius * radius])
+      .value(function(d) { return d.size; });
+  arc = d3.svg.arc()
+      .startAngle(function(d) { return d.x; })
+      .endAngle(function(d) { return d.x + d.dx; })
+      .innerRadius(function(d) { return Math.sqrt(d.y); })
+      .outerRadius(function(d) { return Math.sqrt(d.y + d.dy); });
+  // Basic setup of page elements.
+  initializeBreadcrumbTrail();
+  //drawLegend();
+  //d3.select("#togglelegend").on("click", toggleLegend);
+
+  // Bounding circle underneath the sunburst, to make it easier to detect
+  // when the mouse leaves the parent g.
+  vis = d3.select("#chart").append("svg:svg")
+      .attr("width", width)
+      .attr("height", height)
+      .append("svg:g")
+      .attr("id", "container")
+      .attr("transform", "translate(" + width / 2 + "," + height / 2 + ")");
+  vis.append("svg:circle").attr("r", radius)
+      .style("opacity", 0);
+
+  // For efficiency, filter nodes to keep only those large enough to see.
+  var nodes = partition.nodes(json)
+    .filter(function(d) {
+      return (d.dx > 0.005); // 0.005 radians = 0.29 degrees
+    });
+
+  var path = vis.data([json]).selectAll("path")
+    .data(nodes)
+    .enter().append("svg:path")
+    .attr("display", function(d) { return d.depth ? null : "none"; })
+    .attr("d", arc)
+    .attr("fill-rule", "evenodd")
+    .attr("fill", colorMap)
+    .style("opacity", 1)
+    .on("mouseover", mouseover);
+  // Add the mouseleave handler to the bounding circle.
+  d3.select("#container").on("mouseleave", mouseleave);
+
+  // Get total size of the tree = value of root node from partition.
+  totalSize = path.node().__data__.value;
+}
+
+  // Take a 2-column CSV and transform it into a hierarchical structure 
suitable
+  // for a partition layout. The first column is a sequence of step names, from
+  // root to leaf, separated by hyphens. The second column is a count of how
+  // often that sequence occurred.
+function  buildHierarchy(csv) {
+  var root = {"name": "root", "children": []};
+  for (var i = 0; i < csv.length; i++) {
+    var sequence = csv[i][0];
+    var size = +csv[i][1];
+    if (isNaN(size)) { // e.g. if this is a header row
+      continue;
+    }
+    var parts = sequence.split("-");
+    var currentNode = root;
+    for (var j = 0; j < parts.length; j++) {
+      var children = currentNode["children"];
+      var nodeName = parts[j];
+      var childNode;
+      if (j + 1 < parts.length) {
+        // Not yet at the end of the sequence; move down the tree.
+        var foundChild = false;
+        for (var k = 0; k < children.length; k++) {
+          if (children[k]["name"] === nodeName) {
+            childNode = children[k];
+            foundChild = true;
+            break;
+          }
+        }
+        // If we don't already have a child node for this branch, create it.
+        if (!foundChild) {
+          childNode = {"name": nodeName, "children": []};
+          children.push(childNode);
+        }
+        currentNode = childNode;
+      } else {
+        // Reached the end of the sequence; create a leaf node.
+        childNode = {"name": nodeName, "size": size, "children": [], 
"sequence": sequence};
+        children.push(childNode);
+      }
+    }
+  }
+  return root;
+}
+
+// Fade all but the current sequence, and show it in the breadcrumb trail.
+function mouseover(d) {
+  //var percentage = (100 * d.value / totalSize).toPrecision(3);
+  //var percentageString = percentage + "%";
+  var percentageString = d.value;
+
+  d3.select("#percentage").html('<p align="center" style="font-size: 
150%;"><b>' + percentageString +
+      '</b></p><br/><p align="center">(' + d.name + ')</p>');
+  d3.select("#explanation").style("visibility", "");
+
+  var sequenceArray = getAncestors(d);
+  updateBreadcrumbs(sequenceArray, percentageString);
+
+  // Fade all the segments.
+  d3.selectAll("path").style("opacity", 0.2);
+
+  // Then highlight only those that are an ancestor of the current segment.
+  vis.selectAll("path")
+    .filter(function(node) {
+        return (sequenceArray.indexOf(node) >= 0);
+    })
+    .style("opacity", 1);
+}
+
+// Restore everything to full opacity when moving off the visualization.
+function mouseleave() {
+  // Hide the breadcrumb trail
+  d3.select("#trail").style("visibility", "hidden");
+
+  // Deactivate all segments during transition.
+  d3.selectAll("path").on("mouseover", null);
+
+  // Transition each segment to full opacity and then reactivate it.
+  d3.selectAll("path")
+    .transition()
+    .duration(1000)
+    .style("opacity", 1)
+    .each("end", function() {
+      d3.select(this).on("mouseover", mouseover);
+    });
+
+  d3.select("#explanation")
+    .style("visibility", "hidden");
+}
+
+function initializeBreadcrumbTrail() {
+  // Add the svg area.
+  var trail = d3.select("#sequence").append("svg:svg")
+    .attr("width", width)
+    .attr("height", 50)
+    .attr("id", "trail");
+  // Add the label at the end, for the percentage.
+  trail.append("svg:text")
+    .attr("id", "endlabel")
+    .style("fill", "#000");
+}
+
+// Generate a string that describes the points of a breadcrumb polygon.
+function breadcrumbPoints(d, i) {
+  var points = [];
+  points.push("0,0");
+  points.push(b.w + ",0");
+  points.push(b.w + b.t + "," + (b.h / 2));
+  points.push(b.w + "," + b.h);
+  points.push("0," + b.h);
+  if (i > 0) { // Leftmost breadcrumb; don't include 6th vertex.
+    points.push(b.t + "," + (b.h / 2));
+  }
+  return points.join(" ");
+}
+
+// Update the breadcrumb trail to show the current sequence and percentage.
+function updateBreadcrumbs(nodeArray, percentageString) {
+  // Data join; key function combines name and depth (= position in sequence).
+  var g = d3.select("#trail")
+      .selectAll("g")
+      .data(nodeArray, function(d) { return d.name + d.depth; });
+
+  // Add breadcrumb and label for entering nodes.
+  var entering = g.enter().append("svg:g");
+
+  entering.append("svg:polygon")
+      .attr("points", breadcrumbPoints)
+      .attr("fill", colorMap);
+
+  entering.append("svg:text")
+      .attr("x", (b.w + b.t) / 2)
+      .attr("y", b.h / 2)
+      .attr("dy", "0.35em")
+      .attr("text-anchor", "middle")
+      .text(function(d) { return d.name; });
+
+  // Set position for entering and updating nodes.
+  g.attr("transform", function(d, i) {
+    return "translate(" + i * (b.w + b.s) + ", 0)";
+  });
+
+  // Remove exiting nodes.
+  g.exit().remove();
+
+  // Now move and update the percentage at the end.
+  d3.select("#trail").select("#endlabel")
+      .attr("x", (nodeArray.length + 0.5) * (b.w + b.s))
+      .attr("y", b.h / 2)
+      .attr("dy", "0.35em")
+      .attr("text-anchor", "middle")
+      .text(percentageString);
+
+  // Make the breadcrumb trail visible, if it's hidden.
+  d3.select("#trail")
+      .style("visibility", "");
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js
index 44a7c1c..fffaf17 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/apps.js
@@ -17,7 +17,6 @@
  */
 
 import Ember from 'ember';
-import ColumnDef from 'em-table/utils/column-definition';
 import TableDefinition from 'em-table/utils/table-definition';
 import AppTableController from '../app-table-columns';
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js
index 44a7c1c..fffaf17 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-apps/services.js
@@ -17,7 +17,6 @@
  */
 
 import Ember from 'ember';
-import ColumnDef from 'em-table/utils/column-definition';
 import TableDefinition from 'em-table/utils/table-definition';
 import AppTableController from '../app-table-columns';
 

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js
new file mode 100644
index 0000000..61e7823
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow-activity.js
@@ -0,0 +1,125 @@
+/**
+ * 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 TableDef from 'em-table/utils/table-definition';
+import ColumnDef from 'em-table/utils/column-definition';
+import lodash from 'lodash/lodash';
+
+function _createColumns() {
+  var columns = [];
+  columns.push({
+    id: 'flowName',
+    headerTitle: 'Flow Name',
+    contentPath: 'flowName',
+    observePath: true,
+  }, {
+    id: 'user',
+    headerTitle: 'User',
+    contentPath: 'user',
+    observePath: true
+  }, {
+    id: 'uid',
+    headerTitle: 'Flow ID',
+    contentPath: 'uid',
+    observePath: true,
+    cellComponentName: 'em-table-linked-cell',
+    minWidth: "300px",
+    getCellContent: function (row) {
+      return {
+        routeName: 'yarn-flow.info',
+        id: row.get('uid'),
+        displayText: row.get('uid')
+      };
+    }
+  }, {
+    id: 'lastExecDate',
+    headerTitle: 'Last Execution Date',
+    contentPath: 'lastExecDate',
+    observePath: true
+  });
+  return ColumnDef.make(columns);
+}
+
+function _getAggregatedFlowsData(flows) {
+  var aggregatedFlows = [];
+  flows = flows? flows.get('content') : [];
+
+  var aggregated = lodash.groupBy(flows, function(flow) {
+    return flow.getRecord().get('uid');
+  });
+
+  lodash.forIn(aggregated, function(flows) {
+    let flowsInAsc = lodash.sortBy(flows, function(flow) {
+      return flow.getRecord().get('lastExecDate');
+    });
+    let flowsInDesc = flowsInAsc.reverse();
+    aggregatedFlows.push(flowsInDesc[0].getRecord());
+  });
+
+  return aggregatedFlows;
+}
+
+function _createRows(flows) {
+  var data = [],
+      aggregatedFlows = null,
+      row = null;
+
+  aggregatedFlows = _getAggregatedFlowsData(flows);
+
+  aggregatedFlows.forEach(function(flow) {
+    row = Ember.Object.create({
+      user: flow.get('user'),
+      flowName: flow.get('flowName'),
+      uid: flow.get('uid'),
+      lastExecDate: flow.get('lastExecDate')
+    });
+    data.push(row);
+  });
+
+  return Ember.A(data);
+}
+
+export default Ember.Controller.extend({
+  breadcrumbs: [{
+    text: "Home",
+    routeName: 'application'
+  }, {
+    text: "Flow Activities",
+    routeName: 'yarn-flow-activity',
+  }],
+
+  columns: _createColumns(),
+
+  rows: Ember.computed('model', function() {
+    return _createRows(this.get('model'));
+  }),
+
+  tableDefinition: TableDef.create({
+    sortColumnId: 'lastExecDate',
+    sortOrder: 'desc'
+  }),
+
+  getLastFlowExecutionInfoByFlowUid: function(uid) {
+    var aggregatedFlows = _getAggregatedFlowsData(this.get('model'));
+    var recent = aggregatedFlows.find(function(flow) {
+      return flow.get('uid') === uid;
+    });
+    return recent;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js
new file mode 100644
index 0000000..216ab11
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow.js
@@ -0,0 +1,36 @@
+/**
+ * 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';
+
+export default Ember.Controller.extend({
+  breadcrumbs: Ember.computed("model.flowUid", function() {
+    var flowUid = this.get('model.flowUid');
+    return [{
+      text: "Home",
+      routeName: 'application'
+    }, {
+      text: "Flow Activities",
+      routeName: 'yarn-flow-activity'
+    }, {
+      text: `Flow Info [${flowUid}]`,
+      routeName: 'yarn-flow.info',
+      model: flowUid
+    }];
+  })
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js
new file mode 100644
index 0000000..fc4dd23
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/info.js
@@ -0,0 +1,66 @@
+/**
+ * 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 Converter from 'yarn-ui/utils/converter';
+
+export default Ember.Controller.extend({
+  flowUid: function() {
+    return this.get('model.flowUid');
+  }.property('model.flowUid'),
+
+  flowLastExecutionDate: function() {
+    if (this.get('model.lastFlowExecutionInfo')) {
+      return this.get('model.lastFlowExecutionInfo').get('lastExecDate');
+    } else {
+      return '';
+    }
+  }.property('model.lastFlowExecutionInfo'),
+
+  flowInfo: function() {
+    var info = {};
+    var firstRunObj = this.get('model.flowRuns').get('firstObject');
+    info.flowUid = this.get('flowUid');
+    info.flowName = firstRunObj.get('flowName');
+    info.user = firstRunObj.get('user');
+    info.lastExecutionDate = this.get('flowLastExecutionDate');
+    info.firstRunStarted = this.get('earliestStartTime');
+    info.lastRunFinished = this.get('latestFinishTime');
+    return info;
+  }.property('model.flowRuns', 'flowLastExecutionDate'),
+
+  earliestStartTime: function() {
+    var earliestStart = Number.MAX_VALUE;
+    this.get('model.flowRuns').forEach(function(flowrun) {
+      if (flowrun.get('createTimeRaw') < earliestStart) {
+        earliestStart = flowrun.get('createTimeRaw');
+      }
+    });
+    return Converter.timeStampToDate(earliestStart);
+  }.property('model.flowRuns'),
+
+  latestFinishTime: function() {
+    var latestFinish = 0;
+    this.get('model.flowRuns').forEach(function(flowrun) {
+      if (flowrun.get('endTimeRaw') > latestFinish) {
+        latestFinish = flowrun.get('endTimeRaw');
+      }
+    });
+    return Converter.timeStampToDate(latestFinish);
+  }.property('model.flowRuns')
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js
new file mode 100644
index 0000000..def4c12
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flow/runs.js
@@ -0,0 +1,178 @@
+/**
+ * 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 TableDef from 'em-table/utils/table-definition';
+import ColumnDef from 'em-table/utils/column-definition';
+import Converter from 'yarn-ui/utils/converter';
+
+function createColumn() {
+  var columns = [];
+
+  // Generate columns
+  columns.push({
+    id: 'runid',
+    headerTitle: 'Run ID',
+    contentPath: 'runid',
+    cellComponentName: 'em-table-linked-cell',
+    minWidth: "300px",
+    getCellContent: function (row) {
+      return {
+        routeName: 'yarn-flowrun.info',
+        id: row.get('uid'),
+        displayText: row.get('shownid')
+      };
+    }
+  });
+
+  columns.push({
+    id: 'runDurationTs',
+    headerTitle: 'Run Duration',
+    contentPath: 'runDurationTs',
+    getCellContent: function(row) {
+      return Converter.msToElapsedTimeUnit(row.get('runDurationTs'));
+    }
+  });
+
+  columns.push({
+    id: 'cpuVCores',
+    headerTitle: 'CPU VCores',
+    contentPath: 'cpuVCores',
+    getCellContent: function(row) {
+      if (row.get('cpuVCores') > -1) {
+        return row.get('cpuVCores');
+      }
+      return 'N/A';
+    }
+  });
+
+  columns.push({
+    id: 'memoryUsed',
+    headerTitle: 'Memory Used',
+    contentPath: 'memoryUsed',
+    getCellContent: function(row) {
+      if (row.get('memoryUsed') > -1) {
+        return Converter.memoryBytesToMB(row.get('memoryUsed'));
+      }
+      return 'N/A';
+    }
+  });
+
+  columns.push({
+    id: 'createTime',
+    headerTitle: 'Creation Time',
+    contentPath: 'createTime'
+  });
+
+  columns.push({
+    id: 'endTime',
+    headerTitle: 'End Time',
+    contentPath: 'endTime'
+  });
+
+  return ColumnDef.make(columns);
+}
+
+export default Ember.Controller.extend({
+  vizWidgets: {
+    runDuration: true,
+    cpuVcores: false,
+    memoryUsed: false
+  },
+
+  actions: {
+    addVizWidget(widget) {
+      Ember.set(this.vizWidgets, widget, true);
+    },
+
+    removeVizWidget(widget) {
+      Ember.set(this.vizWidgets, widget, false);
+    }
+  },
+
+  columns: createColumn(),
+
+  tableDefinition: TableDef.create({
+    sortColumnId: 'createTime',
+    sortOrder: 'desc'
+  }),
+
+  elapsedTimeVizData: function() {
+    var data = [];
+    this.get('model.flowRuns').forEach(function(run) {
+      var vizData = run.getElapsedTimeVizDataForBarChart();
+      if (vizData.value > 0) {
+        data.push(vizData);
+      }
+    });
+    data = this.getSortedVizDataInDesc(data);
+    return this.getRefactoredVizData(data);
+  }.property('model.flowRuns'),
+
+  elapsedTimeFormatter: function(tick) {
+    return Converter.msToElapsedTimeUnit(tick, true);
+  },
+
+  cpuVCoresVizData: function() {
+    var data = [];
+    this.get('model.flowRuns').forEach(function(run) {
+      var vizData = run.getCpuVCoresVizDataForBarChart();
+      if (vizData.value > 0) {
+        data.push(vizData);
+      }
+    });
+    data = this.getSortedVizDataInDesc(data);
+    return this.getRefactoredVizData(data);
+  }.property('model.flowRuns'),
+
+  memoryVizData: function() {
+    var data = [];
+    this.get('model.flowRuns').forEach(function(run) {
+      var vizData = run.getMemoryVizDataForBarChart();
+      if (vizData.value > 0) {
+        data.push(vizData);
+      }
+    });
+    data = this.getSortedVizDataInDesc(data);
+    return this.getRefactoredVizData(data);
+  }.property('model.flowRuns'),
+
+  memoryFormatter: function(tick) {
+    return Converter.memoryBytesToMB(tick);
+  },
+
+  onBarChartClick: function() {
+    var self = this;
+    return function(data) {
+      self.transitionToRoute('yarn-flowrun.info', data.flowrunUid);
+    };
+  }.property(),
+
+  getSortedVizDataInDesc: function(data) {
+    return data.sort(function(d1, d2) {
+      return d2.value - d1.value;
+    });
+  },
+
+  getRefactoredVizData: function(data) {
+    data.forEach(function(viz, idx) {
+      viz.label = "Run " + (++idx);
+    }, this);
+    return data;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js
new file mode 100644
index 0000000..6af87ab
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun.js
@@ -0,0 +1,50 @@
+/**
+ * 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';
+
+export default Ember.Controller.extend({
+  breadcrumbs: Ember.computed('model.flowrun_uid', 'model.parentFlowUid', 
function() {
+    var flowRunId = this.get('model.flowrun_uid');
+    var parentFlowUid = this.get('model.parentFlowUid');
+    var crumbs = [{
+      text: "Home",
+      routeName: 'application'
+    }, {
+      text: "Flow Activities",
+      routeName: 'yarn-flow-activity'
+    }];
+    if (parentFlowUid) {
+      crumbs.push({
+        text: `Flow Info [${parentFlowUid}]`,
+        routeName: 'yarn-flow.info',
+        model: parentFlowUid
+      }, {
+        text: `Flow Runs [${parentFlowUid}]`,
+        routeName: 'yarn-flow.runs',
+        model: parentFlowUid
+      });
+    }
+    crumbs.push({
+      text: `Run Info [${flowRunId}]`,
+      routeName: 'yarn-flowrun.info',
+      model: flowRunId
+    });
+    return crumbs;
+  })
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js
new file mode 100644
index 0000000..df2f87e
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/info.js
@@ -0,0 +1,157 @@
+/**
+ * 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 ColumnDef from 'em-table/utils/column-definition';
+import Converter from 'yarn-ui/utils/converter';
+
+function createColumn() {
+  var columns = [];
+
+  // Generate columns
+  columns.push({
+    id: 'appId',
+    headerTitle: 'Application ID',
+    contentPath: 'appId',
+    cellComponentName: 'em-table-linked-cell',
+    minWidth: "300px",
+    getCellContent: function (row) {
+      return {
+        routeName: 'yarn-app',
+        id: row.get('appId'),
+        displayText: row.get('appId')
+      };
+    }
+  });
+
+  columns.push({
+    id: 'appType',
+    headerTitle: 'Application Type',
+    contentPath: 'type'
+  });
+
+  columns.push({
+    id: 'state',
+    headerTitle: 'State',
+    contentPath: 'state',
+    cellComponentName: 'em-table-status-cell',
+  });
+
+  columns.push({
+    id: 'elapsedTs',
+    headerTitle: 'Elapsed Time',
+    contentPath: 'elapsedTs',
+    getCellContent: function(row) {
+      return Converter.msToElapsedTimeUnit(row.get('elapsedTs'));
+    }
+  });
+
+  columns.push({
+    id: 'cpuVCores',
+    headerTitle: 'CPU VCores',
+    contentPath: 'cpuVCores',
+    getCellContent: function(row) {
+      if (row.get('cpuVCores') > -1) {
+        return row.get('cpuVCores');
+      }
+      return 'N/A';
+    }
+  });
+
+  columns.push({
+    id: 'memoryUsed',
+    headerTitle: 'Memory Used',
+    contentPath: 'memoryUsed',
+    getCellContent: function(row) {
+      if (row.get('memoryUsed') > -1) {
+        return Converter.memoryBytesToMB(row.get('memoryUsed'));
+      }
+      return 'N/A';
+    }
+  });
+
+  return ColumnDef.make(columns);
+}
+
+export default Ember.Controller.extend({
+  vizWidgets: {
+    cpuVcores: true,
+    memoryUsed: false
+  },
+
+  actions: {
+    addVizWidget(widget) {
+      Ember.set(this.vizWidgets, widget, true);
+    },
+
+    removeVizWidget(widget) {
+      Ember.set(this.vizWidgets, widget, false);
+    }
+  },
+
+  columns: createColumn(),
+
+  cpuVCoresVizData: function() {
+    var data = [];
+    this.get('model.apps').forEach(function(app) {
+      var vizData = app.getCpuVCoresVizDataForBarChart();
+      if (vizData.value > 0) {
+        data.push(vizData);
+      }
+    });
+    data = this.getSortedVizDataInDesc(data);
+    return this.getRefactoredVizData(data);
+  }.property('model.apps'),
+
+  memoryVizData: function() {
+    var data = [];
+    this.get('model.apps').forEach(function(app) {
+      var vizData = app.getMemoryVizDataForBarChart();
+      if (vizData.value > 0) {
+        data.push(vizData);
+      }
+    });
+    data = this.getSortedVizDataInDesc(data);
+    return this.getRefactoredVizData(data);
+  }.property('model.apps'),
+
+  memoryFormatter: function(tick) {
+    return Converter.memoryBytesToMB(tick);
+  },
+
+  onBarChartClick: function() {
+    var self = this;
+    return function(data) {
+      self.transitionToRoute('yarn-app', data.appId);
+    };
+  }.property(),
+
+  getSortedVizDataInDesc: function(data) {
+    return data.sort(function(d1, d2) {
+      return d2.value - d1.value;
+    });
+  },
+
+  getRefactoredVizData: function(data) {
+    data.forEach(function(viz, idx) {
+      viz.appId = viz.label;
+      viz.label = "App " + (++idx);
+    }, this);
+    return data;
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js
new file mode 100644
index 0000000..97b1e07
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-flowrun/metrics.js
@@ -0,0 +1,126 @@
+/**
+ * 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 ColumnDef from 'em-table/utils/column-definition';
+
+function _createColumns() {
+  var columns = [];
+
+  columns.push({
+    id: 'name',
+    headerTitle: 'Name',
+    contentPath: 'name',
+    observePath: true,
+    cellComponentName: 'em-table-html-cell',
+    getCellContent: function(row) {
+      var plainName = row.name;
+      if (plainName.indexOf('MAP:') > -1 || plainName.indexOf('REDUCE:') > -1) 
{
+        plainName = plainName.substring(plainName.indexOf(':') + 1);
+      }
+      return `<span>${plainName}</span>`;
+    }
+  }, {
+    id: 'value',
+    headerTitle: 'Value',
+    contentPath: 'value',
+    observePath: true
+  });
+
+  return ColumnDef.make(columns);
+}
+
+export default Ember.Controller.extend({
+  mapMetrics: null,
+  reduceMetrics: null,
+  generalMetrics: null,
+
+  columns: Ember.computed(function() {
+    return _createColumns(this.get('model.flowrun_uid'));
+  }),
+
+  metricsObserver: Ember.observer('model.flowrun', function() {
+    var metrics = this.get('model.flowrun.metrics');
+    var mapConfigs = [],
+        reduceConfigs = [],
+        generalConfigs = [];
+
+    metrics.forEach(function(metric) {
+      let id = metric.id;
+      if (id.startsWith('MAP:')) {
+        mapConfigs.push(metric);
+      } else if (id.startsWith('REDUCE:')) {
+        reduceConfigs.push(metric);
+      } else {
+        generalConfigs.push(metric);
+      }
+    }, this);
+
+    this.set('mapMetrics', mapConfigs);
+    this.set('reduceMetrics', reduceConfigs);
+    this.set('generalMetrics', generalConfigs);
+  }),
+
+  mapConfigRows: Ember.computed('mapMetrics', function() {
+    var row = null,
+        data = [];
+
+    this.get('mapMetrics').forEach(function(map) {
+      let value = map.values[Object.keys(map.values)[0]];
+      row = Ember.Object.create({
+        name: map.id,
+        value: value
+      });
+      data.push(row);
+    }, this);
+
+    return Ember.A(data);
+  }),
+
+  reduceConfigRows: Ember.computed('reduceMetrics', function() {
+    var row = null,
+        data = [];
+
+    this.get('reduceMetrics').forEach(function(map) {
+      let value = map.values[Object.keys(map.values)[0]];
+      row = Ember.Object.create({
+        name: map.id,
+        value: value
+      });
+      data.push(row);
+    }, this);
+
+    return Ember.A(data);
+  }),
+
+  generalConfigRows: Ember.computed('generalMetrics', function() {
+    var row = null,
+        data = [];
+
+    this.get('generalMetrics').forEach(function(map) {
+      let value = map.values[Object.keys(map.values)[0]];
+      row = Ember.Object.create({
+        name: map.id,
+        value: value
+      });
+      data.push(row);
+    }, this);
+
+    return Ember.A(data);
+  })
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js
index eeb6205..a2c80f7 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/controllers/yarn-services.js
@@ -18,9 +18,19 @@
 
 import Ember from 'ember';
 import AppTableController from './app-table-columns';
-
+import TableDefinition from 'em-table/utils/table-definition';
 
 export default AppTableController.extend({
+  queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 
'rowCount'],
+  tableDefinition: TableDefinition.create({
+    sortColumnId: 'stTime',
+    sortOrder: 'desc'
+  }),
+  searchText: Ember.computed.alias('tableDefinition.searchText'),
+  sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'),
+  sortOrder: Ember.computed.alias('tableDefinition.sortOrder'),
+  pageNum: Ember.computed.alias('tableDefinition.pageNum'),
+  rowCount: Ember.computed.alias('tableDefinition.rowCount'),
 
   breadcrumbs: [{
     text: "Home",

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js
new file mode 100644
index 0000000..a90bf36
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/mixins/app-attempt.js
@@ -0,0 +1,66 @@
+/**
+ * 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';
+
+export default Ember.Mixin.create({
+  fetchAppInfoFromRMorATS(appId, store) {
+    return new Ember.RSVP.Promise(function(resolve, reject) {
+      store.find('yarn-app', appId).then(function(rmApp) {
+        resolve(rmApp);
+      }, function() {
+        store.find('yarn-app-timeline', appId).then(function(atsApp) {
+          resolve(atsApp);
+        }, function() {
+          console.error('Error:', 'Application not found in RM or ATS for 
appId: ' + appId);
+          reject(null);
+        });
+      });
+    });
+  },
+
+  fetchAttemptInfoFromRMorATS(attemptId, store) {
+    return new Ember.RSVP.Promise(function(resolve, reject) {
+      store.findRecord('yarn-app-attempt', attemptId, {reload: 
true}).then(function(rmAttempt) {
+        resolve(rmAttempt);
+      }, function() {
+        store.findRecord('yarn-timeline-appattempt', attemptId, {reload: 
true}).then(function(atsAttempt) {
+          resolve(atsAttempt);
+        }, function() {
+          console.error('Error:', 'Application attempt not found in RM or ATS 
for attemptId: ' + attemptId);
+          reject(null);
+        });
+      });
+    });
+  },
+
+  fetchAttemptListFromRMorATS(appId, store) {
+    return new Ember.RSVP.Promise(function(resolve, reject) {
+      store.query('yarn-app-attempt', {appId: 
appId}).then(function(rmAttempts) {
+        resolve(rmAttempts);
+      }, function() {
+        store.query('yarn-timeline-appattempt', {appId: 
appId}).then(function(atsAttempts) {
+          resolve(atsAttempts);
+        }, function() {
+          console.error('Error:', 'Application attempts not found in RM or ATS 
for appId: ' + appId);
+          reject(null);
+        });
+      });
+    });
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js
index c83eb2e..dd95765 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-attempt.js
@@ -74,7 +74,7 @@ export default DS.Model.extend({
     if (!this.get("containerId")) {
       return this.get("id");
     }
-    return "attempt_" + 
+    return "attempt_" +
            
parseInt(Converter.containerIdToAttemptId(this.get("containerId")).split("_")[3]);
   }.property("containerId"),
 
@@ -119,13 +119,12 @@ export default DS.Model.extend({
     if (elapsedMs <= 0) {
       elapsedMs = Date.now() - this.get("startTs");
     }
-
-    return Converter.msToElapsedTime(elapsedMs);
+    return Converter.msToElapsedTimeUnit(elapsedMs);
   }.property(),
 
   tooltipLabel: function() {
-    return "<p>Id:" + this.get("id") + 
-           "</p><p>ElapsedTime:" + 
+    return "<p>Id:" + this.get("id") +
+           "</p><p>ElapsedTime:" +
            String(this.get("elapsedTime")) + "</p>";
   }.property(),
 
@@ -141,4 +140,4 @@ export default DS.Model.extend({
     return this.get("state");
   }.property(),
 
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js
new file mode 100644
index 0000000..a8a7471
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-flowrun.js
@@ -0,0 +1,52 @@
+/**
+ * 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 Converter from 'yarn-ui/utils/converter';
+
+export default DS.Model.extend({
+  appId: DS.attr('string'),
+  type: DS.attr('string'),
+  uid: DS.attr('string'),
+  metrics: DS.attr('array'),
+  startedTs: DS.attr('number'),
+  finishedTs: DS.attr('number'),
+  state: DS.attr('string'),
+  cpuVCores: DS.attr('number'),
+  memoryUsed: DS.attr('number'),
+
+  elapsedTs: function() {
+    return this.get('finishedTs') - this.get('startedTs');
+  }.property('startedTs', 'finishedTs'),
+
+  getCpuVCoresVizDataForBarChart: function() {
+    return {
+      label: this.get('appId'),
+      value: this.get('cpuVCores'),
+      tooltip: this.get("appId") + "<br>" + 'CPU VCores: ' + 
this.get('cpuVCores')
+    };
+  },
+
+  getMemoryVizDataForBarChart: function() {
+    return {
+      label: this.get('appId'),
+      value: this.get('memoryUsed'),
+      tooltip: this.get("appId") + "<br>" + 'Memory Used: ' + 
Converter.memoryBytesToMB(this.get('memoryUsed'))
+    };
+  }
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js
new file mode 100644
index 0000000..fa5223f
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-app-timeline.js
@@ -0,0 +1,105 @@
+/**
+ * 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 Converter from 'yarn-ui/utils/converter';
+
+export default DS.Model.extend({
+  appName: DS.attr('string'),
+  user: DS.attr('string'),
+  queue: DS.attr('string'),
+  state: DS.attr('string'),
+  startTime: DS.attr('string'),
+  elapsedTime: DS.attr('string'),
+  finalStatus: DS.attr('string'),
+  finishedTime: DS.attr('finishedTime'),
+  progress: DS.attr('number'),
+  diagnostics: DS.attr('string'),
+  amContainerLogs: DS.attr('string'),
+  amHostHttpAddress: DS.attr('string'),
+  logAggregationStatus: DS.attr('string'),
+  unmanagedApplication: DS.attr('string'),
+  amNodeLabelExpression: DS.attr('string'),
+  applicationTags: DS.attr('string'),
+  applicationType: DS.attr('string'),
+  priority: DS.attr('number'),
+  allocatedMB: DS.attr('number'),
+  allocatedVCores: DS.attr('number'),
+  runningContainers: DS.attr('number'),
+  memorySeconds: DS.attr('number'),
+  vcoreSeconds: DS.attr('number'),
+  preemptedResourceMB: DS.attr('number'),
+  preemptedResourceVCores: DS.attr('number'),
+  numNonAMContainerPreempted: DS.attr('number'),
+  numAMContainerPreempted: DS.attr('number'),
+  clusterUsagePercentage: DS.attr('number'),
+  queueUsagePercentage: DS.attr('number'),
+  currentAppAttemptId: DS.attr('string'),
+
+  isFailed: function() {
+    return this.get('finalStatus') === "FAILED";
+  }.property("finalStatus"),
+
+  validatedFinishedTs: function() {
+    if (this.get("finishedTime") < this.get("startTime")) {
+      return "";
+    }
+    return this.get("finishedTime");
+  }.property("finishedTime"),
+
+  formattedElapsedTime: function() {
+    return Converter.msToElapsedTimeUnit(this.get('elapsedTime'));
+  }.property('elapsedTime'),
+
+  allocatedResource: function() {
+    return Converter.resourceToString(this.get("allocatedMB"), 
this.get("allocatedVCores"));
+  }.property("allocatedMB", "allocatedVCores"),
+
+  preemptedResource: function() {
+    return Converter.resourceToString(this.get("preemptedResourceMB"), 
this.get("preemptedResourceVCores"));
+  }.property("preemptedResourceMB", "preemptedResourceVCores"),
+
+  aggregatedResourceUsage: function() {
+    return Converter.resourceToString(this.get("memorySeconds"), 
this.get("vcoreSeconds")) + " (× Secs)";
+  }.property("memorySeconds", "vcoreSeconds"),
+
+  progressStyle: function() {
+    return "width: " + this.get("progress") + "%";
+  }.property("progress"),
+
+  runningContainersNumber: function() {
+    if(this.get("runningContainers") < 0) {
+      return 0;
+    }
+    return this.get("runningContainers");
+  }.property("progress"),
+
+  finalStatusStyle: function() {
+    var style = "default";
+    var finalStatus = this.get("finalStatus");
+    if (finalStatus === "KILLED") {
+      style = "warning";
+    } else if (finalStatus === "FAILED") {
+      style = "danger";
+    } else {
+      style = "success";
+    }
+
+    return "label label-" + style;
+  }.property("finalStatus")
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js
index bd9cea7..7f39345 100644
--- 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-container.js
@@ -52,13 +52,12 @@ export default DS.Model.extend({
     if (elapsedMs <= 0) {
       elapsedMs = Date.now() - this.get("startTs");
     }
-
-    return Converter.msToElapsedTime(elapsedMs);
+    return Converter.msToElapsedTimeUnit(elapsedMs);
   }.property(),
 
   tooltipLabel: function() {
-    return "<p>Id:" + this.get("id") + 
-           "</p><p>ElapsedTime:" + 
+    return "<p>Id:" + this.get("id") +
+           "</p><p>ElapsedTime:" +
            String(this.get("elapsedTime")) + "</p>";
   }.property(),
-});
\ No newline at end of file
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.js
new file mode 100644
index 0000000..a06d6ab
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-entity.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';
+
+export default DS.Model.extend({
+  entityId: DS.attr('string'),
+  type: DS.attr('string'),
+  uid: DS.attr('string'),
+  metrics: DS.attr('array')
+});

http://git-wip-us.apache.org/repos/asf/hadoop/blob/46d9c4ca/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js
----------------------------------------------------------------------
diff --git 
a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js
 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js
new file mode 100644
index 0000000..1095cfe
--- /dev/null
+++ 
b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/src/main/webapp/app/models/yarn-flow-activity.js
@@ -0,0 +1,28 @@
+/**
+ * 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';
+
+export default DS.Model.extend({
+  cluster: DS.attr('string'),
+  flowName: DS.attr('string'),
+  lastExecDate: DS.attr('string'),
+  user: DS.attr('string'),
+  flowruns: DS.attr('string'),
+  uid: DS.attr('string')
+});


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscr...@hadoop.apache.org
For additional commands, e-mail: common-commits-h...@hadoop.apache.org

Reply via email to