http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/task.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/task.js 
b/tez-ui/src/main/webapp/app/controllers/task.js
new file mode 100644
index 0000000..ffd4ffe
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/task.js
@@ -0,0 +1,54 @@
+/**
+ * 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 ParentController from './parent';
+
+export default ParentController.extend({
+  breadcrumbs: Ember.computed("model.dag", function () {
+    var dagName = this.get("model.dag.name"),
+        vertexName = this.get("model.vertexName") || 
this.get("model.vertexIndex"),
+        taskIndex = this.get("model.index");
+
+    return [{
+      text: `DAG [ ${dagName} ]`,
+      routeName: "dag.index",
+      model: this.get("model.dagID")
+    },{
+      text: `Vertex [ ${vertexName} ]`,
+      routeName: "vertex.index",
+      model: this.get("model.vertexID")
+    },{
+      text: `Task [ ${taskIndex} ]`,
+      routeName: "task.index",
+      model: this.get("model.entityID")
+    }];
+  }),
+
+  tabs: [{
+    text: "Task Details",
+    routeName: "task.index"
+  }, {
+    text: "Task Counters",
+    routeName: "task.counters"
+  }, {
+    text: "Task Attempts",
+    routeName: "task.attempts"
+  }]
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/task/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/task/attempts.js 
b/tez-ui/src/main/webapp/app/controllers/task/attempts.js
new file mode 100644
index 0000000..6f8257f
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/task/attempts.js
@@ -0,0 +1,98 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+import AutoCounterColumn from '../../mixins/auto-counter-column';
+
+export default MultiTableController.extend(AutoCounterColumn, {
+  breadcrumbs: [{
+    text: "Task Attempts",
+    routeName: "task.attempts",
+  }],
+
+  columns: ColumnDefinition.make([{
+    id: 'index',
+    headerTitle: 'Attempt No',
+    contentPath: 'index',
+    cellComponentName: 'em-table-linked-cell',
+    getCellContent: function (row) {
+      return {
+        routeName: "attempt",
+        model: row.get("entityID"),
+        text: row.get("index")
+      };
+    }
+  },{
+    id: 'status',
+    headerTitle: 'Status',
+    contentPath: 'status',
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
+  },{
+    id: 'progress',
+    headerTitle: 'Progress',
+    contentPath: 'progress',
+    cellComponentName: 'em-table-progress-cell',
+    observePath: true
+  },{
+    id: 'startTime',
+    headerTitle: 'Start Time',
+    contentPath: 'startTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'endTime',
+    headerTitle: 'End Time',
+    contentPath: 'endTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'duration',
+    headerTitle: 'Duration',
+    contentPath: 'duration',
+    cellDefinition: {
+      type: 'duration'
+    }
+  },{
+    id: 'containerID',
+    headerTitle: 'Container',
+    contentPath: 'containerID'
+  },{
+    id: 'nodeID',
+    headerTitle: 'Node',
+    contentPath: 'nodeID'
+  }, {
+    id: 'log',
+    headerTitle: 'Log',
+    contentPath: 'logURL',
+    cellComponentName: 'em-table-linked-cell',
+    cellDefinition: {
+      target: "_blank"
+    },
+    getCellContent: function (row) {
+      return [{
+        href: row.get("logURL"),
+        text: "View"
+      }, {
+        href: row.get("logURL"),
+        text: "Download",
+        download: true
+      }];
+    }
+  }])
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/task/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/task/counters.js 
b/tez-ui/src/main/webapp/app/controllers/task/counters.js
new file mode 100644
index 0000000..4aa071c
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/task/counters.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 CountersTableController from '../counters-table';
+
+export default CountersTableController.extend({
+  breadcrumbs: [{
+    text: "Task Counters",
+    routeName: "task.counters",
+  }],
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/task/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/task/index.js 
b/tez-ui/src/main/webapp/app/controllers/task/index.js
new file mode 100644
index 0000000..ec48ac4
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/task/index.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 PageController from '../page';
+
+export default PageController.extend({
+  attempts: null,
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/vertex.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/vertex.js 
b/tez-ui/src/main/webapp/app/controllers/vertex.js
new file mode 100644
index 0000000..78f5db9
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/vertex.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 Ember from 'ember';
+
+import ParentController from './parent';
+
+export default ParentController.extend({
+  breadcrumbs: Ember.computed("model.dag", function () {
+    var dagName = this.get("model.dag.name"),
+        vertexName = this.get("model.name") || this.get("model.index");
+
+    return [{
+      text: `DAG [ ${dagName} ]`,
+      routeName: "dag.index",
+      model: this.get("model.dagID")
+    },{
+      text: `Vertex [ ${vertexName} ]`,
+      routeName: "vertex.index",
+      model: this.get("model.vertexID")
+    }];
+  }),
+
+  tabs: [{
+    text: "Vertex Details",
+    routeName: "vertex.index"
+  }, {
+    text: "Vertex Counters",
+    routeName: "vertex.counters"
+  }, {
+    text: "Tasks",
+    routeName: "vertex.tasks"
+  }, {
+    text: "Task Attempts",
+    routeName: "vertex.attempts"
+  }]
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/vertex/attempts.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/vertex/attempts.js 
b/tez-ui/src/main/webapp/app/controllers/vertex/attempts.js
new file mode 100644
index 0000000..bdda7f8
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/vertex/attempts.js
@@ -0,0 +1,110 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+import AutoCounterColumn from '../../mixins/auto-counter-column';
+
+export default MultiTableController.extend(AutoCounterColumn, {
+  breadcrumbs: [{
+    text: "Task Attempts",
+    routeName: "vertex.attempts",
+  }],
+
+  columns: ColumnDefinition.make([{
+    id: 'index',
+    headerTitle: 'Attempt No',
+    contentPath: 'index',
+    cellComponentName: 'em-table-linked-cell',
+    getCellContent: function (row) {
+      return {
+        routeName: "attempt",
+        model: row.get("entityID"),
+        text: row.get("index")
+      };
+    }
+  },{
+    id: 'taskIndex',
+    headerTitle: 'Task Index',
+    contentPath: 'taskIndex',
+    cellComponentName: 'em-table-linked-cell',
+    getCellContent: function (row) {
+      return {
+        routeName: "task",
+        model: row.get("taskID"),
+        text: row.get("taskIndex")
+      };
+    }
+  },{
+    id: 'status',
+    headerTitle: 'Status',
+    contentPath: 'status',
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
+  },{
+    id: 'progress',
+    headerTitle: 'Progress',
+    contentPath: 'progress',
+    cellComponentName: 'em-table-progress-cell',
+    observePath: true
+  },{
+    id: 'startTime',
+    headerTitle: 'Start Time',
+    contentPath: 'startTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'endTime',
+    headerTitle: 'End Time',
+    contentPath: 'endTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'duration',
+    headerTitle: 'Duration',
+    contentPath: 'duration',
+    cellDefinition: {
+      type: 'duration'
+    }
+  },{
+    id: 'containerID',
+    headerTitle: 'Container',
+    contentPath: 'containerID'
+  },{
+    id: 'nodeID',
+    headerTitle: 'Node',
+    contentPath: 'nodeID'
+  }, {
+    id: 'log',
+    headerTitle: 'Log',
+    contentPath: 'logURL',
+    cellComponentName: 'em-table-linked-cell',
+    cellDefinition: {
+      target: "_blank"
+    },
+    getCellContent: function (row) {
+      return [{
+        href: row.get("logURL"),
+        text: "View"
+      }, {
+        href: row.get("logURL"),
+        text: "Download",
+        download: true
+      }];
+    }
+  }])
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/vertex/counters.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/vertex/counters.js 
b/tez-ui/src/main/webapp/app/controllers/vertex/counters.js
new file mode 100644
index 0000000..1213728
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/vertex/counters.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 CountersTableController from '../counters-table';
+
+export default CountersTableController.extend({
+  breadcrumbs: [{
+    text: "Vertex Counters",
+    routeName: "vertex.counters",
+  }],
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/vertex/index.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/vertex/index.js 
b/tez-ui/src/main/webapp/app/controllers/vertex/index.js
new file mode 100644
index 0000000..c14d113
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/vertex/index.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';
+
+import PageController from '../page';
+
+function taskLinkComputerFactory(name) {
+  return Ember.computed(name, function () {
+    var tasks = this.get(name);
+
+    if(tasks) {
+      return tasks.map(function (task) {
+        return {
+          routeName: 'task',
+          model: task,
+          text: task
+        };
+      });
+    }
+  });
+}
+
+export default PageController.extend({
+
+  pathname: Ember.computed(function() {
+    return window.location.pathname;
+  }).volatile(),
+
+  firstTasksToStart: taskLinkComputerFactory("model.firstTasksToStart"),
+  lastTasksToFinish: taskLinkComputerFactory("model.lastTasksToFinish"),
+  shortestDurationTasks: 
taskLinkComputerFactory("model.shortestDurationTasks"),
+  longestDurationTasks: taskLinkComputerFactory("model.longestDurationTasks"),
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/controllers/vertex/tasks.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/controllers/vertex/tasks.js 
b/tez-ui/src/main/webapp/app/controllers/vertex/tasks.js
new file mode 100644
index 0000000..ed26173
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/controllers/vertex/tasks.js
@@ -0,0 +1,72 @@
+/**
+ * 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 MultiTableController from '../multi-table';
+import ColumnDefinition from 'em-table/utils/column-definition';
+
+import AutoCounterColumn from '../../mixins/auto-counter-column';
+
+export default MultiTableController.extend(AutoCounterColumn, {
+  breadcrumbs: [{
+    text: "Tasks",
+    routeName: "vertex.tasks",
+  }],
+
+  columns: ColumnDefinition.make([{
+    id: 'index',
+    headerTitle: 'Task Index',
+    contentPath: 'index',
+    cellComponentName: 'em-table-linked-cell',
+    getCellContent: function (row) {
+      return {
+        routeName: "task",
+        model: row.get("entityID"),
+        text: row.get("index")
+      };
+    }
+  },{
+    id: 'status',
+    headerTitle: 'Status',
+    contentPath: 'status',
+    cellComponentName: 'em-table-status-cell',
+    observePath: true
+  },{
+    id: 'progress',
+    headerTitle: 'Progress',
+    contentPath: 'progress',
+    cellComponentName: 'em-table-progress-cell',
+    observePath: true
+  },{
+    id: 'startTime',
+    headerTitle: 'Start Time',
+    contentPath: 'startTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'endTime',
+    headerTitle: 'End Time',
+    contentPath: 'endTime',
+    cellComponentName: 'date-formatter',
+  },{
+    id: 'duration',
+    headerTitle: 'Duration',
+    contentPath: 'duration',
+    cellDefinition: {
+      type: 'duration'
+    }
+  }])
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/entities/am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/entities/am.js 
b/tez-ui/src/main/webapp/app/entities/am.js
new file mode 100644
index 0000000..56d061d
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/entities/attempt-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/entities/attempt-am.js 
b/tez-ui/src/main/webapp/app/entities/attempt-am.js
new file mode 100644
index 0000000..077c494
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/entities/entity.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/entities/entity.js 
b/tez-ui/src/main/webapp/app/entities/entity.js
new file mode 100644
index 0000000..462a148
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/entities/entity.js
@@ -0,0 +1,181 @@
+/*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 NameMixin from '../mixins/name';
+
+var MoreObject = more.Object;
+
+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);
+    });
+  },
+
+  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;
+      });
+    });
+  },
+
+  normalizeNeed: function(name, needOptions, parentModel, queryParams, 
urlParams) {
+    var need = {
+      name: name,
+      type: name,
+      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, index) {
+    var needLoader,
+        that = this,
+        types = needOptions.type,
+        type;
+
+    if(!Array.isArray(types)) {
+      types = [types];
+    }
+
+    index = index || 0;
+    type = types[index];
+
+    needLoader = loader.queryRecord(
+      type,
+      parentModel.get(needOptions.idKey),
+      options,
+      needOptions.queryParams,
+      needOptions.urlParams
+    );
+
+    needLoader = needLoader.then(function (model) {
+      parentModel.set(needOptions.name, model);
+      parentModel.refreshLoadTime();
+      return model;
+    });
+
+    needLoader = needLoader.catch(function (err) {
+      if(++index < types.length) {
+        return that._loadNeed(loader, parentModel, needOptions, options, 
index);
+      }
+
+      if(needOptions.silent) {
+        parentModel.set(needOptions.name, null);
+        parentModel.refreshLoadTime();
+      }
+      else {
+        throw(err);
+      }
+    });
+
+    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);
+  },
+
+  _loadAllNeeds: function (loader, model, options/*, urlParams*/) {
+    var needsPromise = this.loadAllNeeds(loader, model, options);
+
+    if(needsPromise) {
+      return needsPromise.then(function () {
+        return model;
+      });
+    }
+
+    return model;
+  },
+
+  loadAllNeeds: function (loader, parentModel, options, queryParams, 
urlParams) {
+    var needLoaders = [],
+        that = this,
+        needs = parentModel.get("needs");
+
+    if(needs) {
+      MoreObject.forEach(needs, function (name, needOptions) {
+        needOptions = that.normalizeNeed(name, needOptions, parentModel, 
queryParams, urlParams);
+
+        if(needOptions.loadType !== "demand") {
+          let needLoader = that._loadNeed(loader, parentModel, needOptions, 
options);
+
+          if(needOptions.loadType !== "lazy") {
+            needLoaders.push(needLoader);
+          }
+        }
+      });
+    }
+
+    if(needLoaders.length) {
+      return Ember.RSVP.all(needLoaders);
+    }
+  },
+
+});
+
+export default Entity;

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/entities/task-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/entities/task-am.js 
b/tez-ui/src/main/webapp/app/entities/task-am.js
new file mode 100644
index 0000000..0e41239
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/entities/vertex-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/entities/vertex-am.js 
b/tez-ui/src/main/webapp/app/entities/vertex-am.js
new file mode 100644
index 0000000..15a26da
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/errors/unlinked-promise.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/errors/unlinked-promise.js 
b/tez-ui/src/main/webapp/app/errors/unlinked-promise.js
new file mode 100644
index 0000000..770b095
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/errors/unlinked-promise.js
@@ -0,0 +1,34 @@
+/**
+ * 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';
+
+let UnlinkedPromise = function (errors, message = 'Promise chain was 
unlinked.') {
+  Ember.Error.call(this, message);
+
+  this.errors = errors || [
+    {
+      title: 'Unlinked promise chain.',
+      detail: message
+    }
+  ];
+};
+
+UnlinkedPromise.prototype = Object.create(Ember.Error.prototype);
+
+export default UnlinkedPromise;

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/img/apache-tez-logo-transparent.png
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/img/apache-tez-logo-transparent.png 
b/tez-ui/src/main/webapp/app/img/apache-tez-logo-transparent.png
deleted file mode 100644
index f29455a..0000000
Binary files a/tez-ui/src/main/webapp/app/img/apache-tez-logo-transparent.png 
and /dev/null differ

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/img/apache_tez_logo_lowres.png
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/img/apache_tez_logo_lowres.png 
b/tez-ui/src/main/webapp/app/img/apache_tez_logo_lowres.png
deleted file mode 100644
index 45fd701..0000000
Binary files a/tez-ui/src/main/webapp/app/img/apache_tez_logo_lowres.png and 
/dev/null differ

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/img/glyphicons-halflings.png
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/img/glyphicons-halflings.png 
b/tez-ui/src/main/webapp/app/img/glyphicons-halflings.png
deleted file mode 100644
index 79bc568..0000000
Binary files a/tez-ui/src/main/webapp/app/img/glyphicons-halflings.png and 
/dev/null differ

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/img/tez-favicon.png
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/img/tez-favicon.png 
b/tez-ui/src/main/webapp/app/img/tez-favicon.png
deleted file mode 100644
index 4762bdf..0000000
Binary files a/tez-ui/src/main/webapp/app/img/tez-favicon.png and /dev/null 
differ

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/index.html
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/index.html 
b/tez-ui/src/main/webapp/app/index.html
index 82134e0..757d663 100644
--- a/tez-ui/src/main/webapp/app/index.html
+++ b/tez-ui/src/main/webapp/app/index.html
@@ -15,81 +15,33 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 -->
-<!doctype html>
+
+<!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge">
     <title>Tez UI</title>
+    <meta name="description" content="">
+    <meta name="viewport" content="width=device-width, initial-scale=1">
 
-    <link rel="shortcut icon" href="img/tez-favicon.png" type="image/x-icon">
+    {{content-for 'head'}}
 
-    <!-- build:css styles/main.css -->
-    <link rel="stylesheet" href="styles/main.css">
-    <link rel="stylesheet" href="styles/swimlanes.css">
-    <link rel="stylesheet" 
href="bower_components/ember-table/dist/ember-table.css">
-    <link rel="stylesheet" 
href="bower_components/font-awesome/css/font-awesome.css">
-    <link rel="stylesheet" 
href="bower_components/jquery-ui/themes/smoothness/jquery-ui.css">
-    <link rel="stylesheet" 
href="bower_components/codemirror/lib/codemirror.css">
-    <!-- endbuild -->
+    <link rel="shortcut icon" href="assets/images/favicon.png" 
type="image/x-icon">
 
-  </head>
+    <link rel="stylesheet" href="assets/vendor.css">
+    <link rel="stylesheet" href="assets/tez-ui.css">
 
+    {{content-for 'head-footer'}}
+  </head>
   <body>
-    <!-- build:js(app) scripts/components.js -->
-    <script src="bower_components/jquery/jquery.js"></script>
-    <script src="bower_components/jquery-ui/jquery-ui.js"></script>
-    <script src="bower_components/bootstrap/js/dropdown.js"></script>
-    <script src="bower_components/bootstrap/js/button.js"></script>
-    <script src="bower_components/jquery-ui/ui/datepicker.js"></script>
-    <script src="bower_components/moment/moment.js"></script>
-    <script 
src="bower_components/moment-timezone/builds/moment-timezone-with-data-2010-2020.js"></script>
-    <script src="bower_components/handlebars/handlebars.js"></script>
-    <script src="@@ember"></script>
-    <script src="@@ember_data"></script>
-    <script 
src="bower_components/ember-json-mapper/ember-json-mapper.js"></script>
-    <script src="bower_components/ember-i18n/lib/i18n.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-core.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-basic.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-button.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-modal.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-nav.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-items-action-bar.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-badge.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-label.min.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-progressbar.min.js"></script>
-    <script src="bower_components/antiscroll/antiscroll.js"></script>
-    <script 
src="bower_components/jquery-mousewheel/jquery.mousewheel.js"></script>
-    <script src="bower_components/ember-table/dist/ember-table.js"></script>
-    <script 
src="bower_components/ember-addons.bs_for_ember/dist/js/bs-nav.min.js"></script>
-    <script src="bower_components/d3/d3.js"></script>
-    <script src="bower_components/zip.js/WebContent/zip.js"></script>
-    <script src="bower_components/FileSaver.js/FileSaver.min.js"></script>
-    <script src="bower_components/codemirror/lib/codemirror.js"></script>
-    <script src="bower_components/codemirror/mode/sql/sql.js"></script>
-    <script src="bower_components/codemirror/mode/pig/pig.js"></script>
-    <!-- endbuild -->
-
-    <!-- build:js(.tmp) scripts/templates.js -->
-    <script src="scripts/compiled-templates.js"></script>
-    <!-- endbuild -->
-
-    <!-- build:js(.tmp) scripts/main.js -->
-    <script src="scripts/combined-scripts.js"></script>
-    <!-- endbuild -->
+    {{content-for 'body'}}
 
-    <script src="scripts/configs.js"></script>
+    <script src="config/configs.env" integrity=""></script>
 
-    <div class="error-bar">
-      <div class="main-container">
-        <div class="message-container">
-          <span class="error-icon"></span>&nbsp;
-          <span class="message"></span>
-        </div><div class="close-container">
-          <div class="close">&#65516;</div>
-        </div>
-        <div class="details"></div>
-    </div>
+    <script src="assets/vendor.js"></script>
+    <script src="assets/tez-ui.js"></script>
 
+    {{content-for 'body-footer'}}
   </body>
 </html>
-    

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/entities.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/entities.js 
b/tez-ui/src/main/webapp/app/initializers/entities.js
new file mode 100644
index 0000000..b5afd31
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/entities.js
@@ -0,0 +1,29 @@
+/**
+ * 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 registerWithContainer from "ember-cli-auto-register/register";
+
+export function initialize(application) {
+  registerWithContainer("entity", application);
+  application.inject('entitie', 'store', 'service:store');
+}
+
+export default {
+  name: 'entities',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/env.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/env.js 
b/tez-ui/src/main/webapp/app/initializers/env.js
new file mode 100644
index 0000000..591d989
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/env.js
@@ -0,0 +1,29 @@
+/**
+ * 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.
+ */
+
+export function initialize(application) {
+  application.inject('controller', 'env', 'service:env');
+  application.inject('route', 'env', 'service:env');
+  application.inject('adapter', 'env', 'service:env');
+  application.inject('serializer', 'env', 'service:env');
+}
+
+export default {
+  name: 'env',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/hosts.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/hosts.js 
b/tez-ui/src/main/webapp/app/initializers/hosts.js
new file mode 100644
index 0000000..ec6f7a7
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/hosts.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.
+ */
+
+export function initialize(application) {
+  application.inject('controller', 'hosts', 'service:hosts');
+  application.inject('adapter', 'hosts', 'service:hosts');
+  application.inject('route', 'hosts', 'service:hosts');
+}
+
+export default {
+  name: 'hosts',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/jquery.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/jquery.js 
b/tez-ui/src/main/webapp/app/initializers/jquery.js
new file mode 100644
index 0000000..2c34b1d
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/jquery.js
@@ -0,0 +1,39 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import Ember from 'ember';
+
+export function initialize(/* application */) {
+  Ember.$(document).tooltip({
+    delay: 20,
+    tooltipClass: 'generic-tooltip'
+  });
+
+  Ember.$.ajaxPrefilter(function(options, originalOptions, jqXHR) {
+    jqXHR.requestOptions = originalOptions;
+  });
+
+  Ember.$.ajaxSetup({
+    cache: false
+  });
+}
+
+export default {
+  name: 'jquery',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/loader.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/loader.js 
b/tez-ui/src/main/webapp/app/initializers/loader.js
new file mode 100644
index 0000000..2956d2c
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/loader.js
@@ -0,0 +1,27 @@
+/**
+ * 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.
+ */
+
+export function initialize(application) {
+  application.inject('route', 'loader', 'service:loader');
+  application.inject('entity', 'loader', 'service:loader');
+}
+
+export default {
+  name: 'loader',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/initializers/local-storage.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/initializers/local-storage.js 
b/tez-ui/src/main/webapp/app/initializers/local-storage.js
new file mode 100644
index 0000000..8504c35
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/initializers/local-storage.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.
+ */
+
+export function initialize(application) {
+  application.inject('controller', 'localStorage', 'service:localStorage');
+}
+
+export default {
+  name: 'local-storage',
+  initialize
+};

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/mixins/auto-counter-column.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/mixins/auto-counter-column.js 
b/tez-ui/src/main/webapp/app/mixins/auto-counter-column.js
new file mode 100644
index 0000000..0504d4b
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/mixins/auto-counter-column.js
@@ -0,0 +1,69 @@
+/*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';
+
+var MoreObject = more.Object;
+
+export default Ember.Mixin.create({
+  columnSelectorMessage: "<span class='per-io'>Per-IO counter</span> selection 
wouldn't persist.",
+
+  getCounterColumns: function () {
+    var columns = [],
+        records = this.get("model"),
+        counterHash = {};
+
+    this._super().forEach(function (column) {
+      var groupHash =
+          counterHash[column.counterGroupName] =
+          counterHash[column.counterGroupName] || {};
+      groupHash[column.counterName] = column.counterName;
+    });
+
+    if(records) {
+      records.forEach(function (record) {
+        let counterGroupsHash = Ember.get(record, 'counterGroupsHash');
+
+        if(counterGroupsHash) {
+          MoreObject.forEach(counterGroupsHash, function (groupName, 
countersHash) {
+            var groupHash =
+                counterHash[groupName] =
+                counterHash[groupName] || {};
+
+            MoreObject.forEach(countersHash, function (counterName) {
+              groupHash[counterName] = counterName;
+            });
+          });
+        }
+      });
+    }
+
+    MoreObject.forEach(counterHash, function (groupName, counters) {
+      MoreObject.forEach(counters, function (counterName) {
+        columns.push({
+          counterName: counterName,
+          counterGroupName: groupName
+        });
+      });
+    });
+
+    return columns;
+  }
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/mixins/name.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/mixins/name.js 
b/tez-ui/src/main/webapp/app/mixins/name.js
new file mode 100644
index 0000000..fe0c524
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/mixins/name.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';
+
+export default Ember.Mixin.create({
+
+  name: Ember.computed(function () {
+    var name = this.toString();
+    name = name.substr(0, name.indexOf("::"));
+    name = name.substr(name.indexOf(":") + 1);
+    return name;
+  }),
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/abstract.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/abstract.js 
b/tez-ui/src/main/webapp/app/models/abstract.js
new file mode 100644
index 0000000..24bcbd3
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/abstract.js
@@ -0,0 +1,60 @@
+/**
+ * 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';
+
+export default DS.Model.extend({
+  loadTime: null,
+
+  mergedProperties: ["needs"],
+
+  refreshLoadTime: function () {
+    this.set('loadTime', new Date());
+  },
+
+  //TODO - Find a better alternative to detect property change in a model
+  _notifyProperties: function (keys) {
+    this.refreshLoadTime();
+    return this._super(keys);
+  },
+
+  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/13132ec7/tez-ui/src/main/webapp/app/models/ahs-app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/ahs-app.js 
b/tez-ui/src/main/webapp/app/models/ahs-app.js
new file mode 100644
index 0000000..c18bed9
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/ahs-app.js
@@ -0,0 +1,43 @@
+/**
+ * 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 AbstractModel from './abstract';
+
+export default AbstractModel.extend({
+  attemptID: DS.attr('string'),
+
+  name: DS.attr('string'),
+  queue: DS.attr('string'),
+  user: DS.attr('string'),
+  type: DS.attr('string'),
+
+  status: DS.attr('string'),
+  finalStatus: DS.attr('string'),
+
+  startTime: DS.attr('number'),
+  endTime: DS.attr('number'),
+  duration: Ember.computed("startTime", "endTime", function () {
+    var duration = this.get("endTime") - this.get("startTime");
+    return duration > 0 ? duration : null;
+  }),
+
+  diagnostics: DS.attr('string'),
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/am-timeline.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/am-timeline.js 
b/tez-ui/src/main/webapp/app/models/am-timeline.js
new file mode 100644
index 0000000..bfd03b3
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/models/am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/am.js 
b/tez-ui/src/main/webapp/app/models/am.js
new file mode 100644
index 0000000..46ec75e
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/models/app-rm.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/app-rm.js 
b/tez-ui/src/main/webapp/app/models/app-rm.js
new file mode 100644
index 0000000..34bf6b3
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/models/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/app.js 
b/tez-ui/src/main/webapp/app/models/app.js
new file mode 100644
index 0000000..eabb61f
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/app.js
@@ -0,0 +1,46 @@
+/**
+ * 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';
+
+export default TimelineModel.extend({
+  needs:{
+    app: {
+      type: ["AhsApp", "appRm"],
+      idKey: "appID",
+      silent: true
+    }
+  },
+
+  appID: Ember.computed("entityID", function () {
+    return this.get("entityID").substr(4);
+  }),
+
+  domain: DS.attr("string"),
+
+  user: DS.attr("string"),
+
+  buildTime: DS.attr("string"),
+  tezRevision: DS.attr("string"),
+  tezVersion: DS.attr("string"),
+
+  configs: DS.attr("object"),
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/attempt-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/attempt-am.js 
b/tez-ui/src/main/webapp/app/models/attempt-am.js
new file mode 100644
index 0000000..55722b6
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/models/attempt.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/attempt.js 
b/tez-ui/src/main/webapp/app/models/attempt.js
new file mode 100644
index 0000000..e04c8c1
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/attempt.js
@@ -0,0 +1,76 @@
+/**
+ * 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 AMTimelineModel from './am-timeline';
+
+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")
+        };
+      }
+    }
+  },
+
+  taskID: DS.attr('string'),
+  taskIndex: Ember.computed("taskID", function () {
+    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}`);
+  }),
+
+  dagID: DS.attr('string'),
+  dag: DS.attr('object'), // Auto-loaded by need
+
+  containerID: DS.attr('string'),
+  nodeID: DS.attr('string'),
+
+  logURL: DS.attr('string'),
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/dag-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/dag-am.js 
b/tez-ui/src/main/webapp/app/models/dag-am.js
new file mode 100644
index 0000000..55722b6
--- /dev/null
+++ b/tez-ui/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/13132ec7/tez-ui/src/main/webapp/app/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/dag.js 
b/tez-ui/src/main/webapp/app/models/dag.js
new file mode 100644
index 0000000..8e7b523
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/dag.js
@@ -0,0 +1,70 @@
+/**
+ * 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 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")
+        };
+      }
+    },
+    app: {
+      type: ["AhsApp", "appRm"],
+      idKey: "appID",
+      silent: true
+    }
+  },
+
+  name: DS.attr("string"),
+
+  submitter: DS.attr("string"),
+
+  // Serialize when required
+  vertices: DS.attr('object'),
+  edges: DS.attr('object'),
+  vertexGroups: DS.attr('object'),
+
+  domain: DS.attr("string"),
+  containerLogs: DS.attr("object"),
+  queue: Ember.computed("app", function () {
+    return this.get("app.queue");
+  }),
+
+  vertexIdNameMap: DS.attr("object"),
+
+  callerID: DS.attr("string"),
+  callerType: DS.attr("string"),
+  callerInfo: DS.attr("string"),
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/rm.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/rm.js 
b/tez-ui/src/main/webapp/app/models/rm.js
new file mode 100644
index 0000000..d35ba23
--- /dev/null
+++ b/tez-ui/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"),
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/task-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/task-am.js 
b/tez-ui/src/main/webapp/app/models/task-am.js
new file mode 100644
index 0000000..55722b6
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/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 AMModel from './am';
+
+export default AMModel.extend({
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/task.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/task.js 
b/tez-ui/src/main/webapp/app/models/task.js
new file mode 100644
index 0000000..b2e7f71
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/task.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 DS from 'ember-data';
+
+import AMTimelineModel from './am-timeline';
+
+export default AMTimelineModel.extend({
+  needs: {
+    dag: {
+      type: "dag",
+      idKey: "dagID",
+      silent: true
+    },
+    am: {
+      type: "taskAm",
+      idKey: "entityID",
+      loadType: "demand",
+      queryParams: function (model) {
+        var vertexIndex = parseInt(model.get("vertexIndex")),
+            taskIndex = parseInt(model.get("index"));
+        return {
+          taskID: `${vertexIndex}_${taskIndex}`,
+          dagID: parseInt(model.get("dag.index")),
+          counters: "*"
+        };
+      },
+      urlParams: function (model) {
+        return {
+          app_id: model.get("appID")
+        };
+      }
+    }
+  },
+
+  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}`);
+  }),
+
+  dagID: DS.attr('string'),
+  dag: DS.attr('object'), // Auto-loaded by need
+
+  failedTaskAttempts: DS.attr('number'),
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/timeline.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/timeline.js 
b/tez-ui/src/main/webapp/app/models/timeline.js
new file mode 100644
index 0000000..a0b83e2
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/timeline.js
@@ -0,0 +1,91 @@
+/**
+ * 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 Ember from 'ember';
+
+import AbstractModel from './abstract';
+
+export default AbstractModel.extend({
+
+  needs:{
+    app: {
+      type: ["appRm", "AhsApp"],
+      idKey: "appID",
+      silent: true
+    }
+  },
+
+  appID: Ember.computed("entityID", function () {
+    var idParts = this.get("entityID").split("_");
+    return `application_${idParts[1]}_${idParts[2]}`;
+  }),
+  app: DS.attr("object"), // Either RMApp or AHSApp
+
+  atsStatus: DS.attr("string"),
+  status: Ember.computed("atsStatus", "app.status", "app.finalStatus", 
function () {
+    var status = this.get("atsStatus"),
+        yarnStatus = this.get("app.status");
+
+    if (status !== 'RUNNING' || (yarnStatus !== 'FINISHED' && yarnStatus !== 
'KILLED' && yarnStatus !== 'FAILED')) {
+      return status;
+    }
+
+    if (yarnStatus === 'KILLED' || yarnStatus === 'FAILED') {
+      return yarnStatus;
+    }
+
+    return this.get("app.finalStatus");
+  }),
+
+  progress: Ember.computed("status", function () {
+    return this.get("status") === "SUCCEEDED" ? 1 : null;
+  }),
+
+  startTime: DS.attr("number"),
+  endTime: DS.attr("number"),
+  duration: Ember.computed("startTime", "endTime", function () {
+    var duration = this.get("endTime") - this.get("startTime");
+    return duration > 0 ? duration : null;
+  }),
+
+  // Hash will be created only on demand, till then counters will be stored in 
_counterGroups
+  _counterGroups: DS.attr('object'),
+  counterGroupsHash: Ember.computed("_counterGroups", function () {
+    var counterHash = {},
+        counterGroups = this.get("_counterGroups") || [];
+
+    counterGroups.forEach(function (group) {
+      var counters = group.counters,
+          groupHash;
+
+      groupHash = counterHash[group.counterGroupName] = 
counterHash[group.counterGroupName] || {};
+
+      counters.forEach(function (counter) {
+        groupHash[counter.counterName] = counter.counterValue;
+      });
+    });
+
+    return counterHash;
+  }),
+
+  diagnostics: DS.attr('string'),
+
+  events: DS.attr('object'),
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/vertex-am.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/vertex-am.js 
b/tez-ui/src/main/webapp/app/models/vertex-am.js
new file mode 100644
index 0000000..a20d171
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/vertex-am.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 DS from 'ember-data';
+
+import AMModel from './am';
+
+export default AMModel.extend({
+
+  totalTasks: DS.attr("number"),
+  succeededTasks: DS.attr("number"),
+  runningTasks: DS.attr("number"),
+  pendingTasks: DS.attr("number"),
+  failedTaskAttempts: DS.attr("number"),
+  killedTaskAttempts: DS.attr("number"),
+
+  initTime: DS.attr('number'),
+  startTime: DS.attr('number'),
+  endTime: DS.attr('number'),
+  firstTaskStartTime: DS.attr('number'),
+  lastTaskFinishTime: DS.attr('number'),
+
+});

http://git-wip-us.apache.org/repos/asf/tez/blob/13132ec7/tez-ui/src/main/webapp/app/models/vertex.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/models/vertex.js 
b/tez-ui/src/main/webapp/app/models/vertex.js
new file mode 100644
index 0000000..e54bff2
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/models/vertex.js
@@ -0,0 +1,146 @@
+/**
+ * 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 AMTimelineModel from './am-timeline';
+
+function valueComputerFactory(path1, path2) {
+  return function () {
+    var value = this.get(path1);
+    if(value === undefined || value === null){
+      value = this.get(path2);
+    }
+    return value;
+  };
+}
+
+export default AMTimelineModel.extend({
+  needs: {
+    dag: {
+      type: "dag",
+      idKey: "dagID",
+      silent: true
+    },
+    am: {
+      type: "vertexAm",
+      idKey: "entityID",
+      loadType: "demand",
+      queryParams: function (model) {
+        return {
+          vertexID: parseInt(model.get("index")),
+          dagID: parseInt(model.get("dag.index")),
+          counters: "*"
+        };
+      },
+      urlParams: function (model) {
+        return {
+          app_id: model.get("appID")
+        };
+      }
+    }
+  },
+
+  name: DS.attr('string'),
+
+  _initTime: DS.attr('number'),
+  _startTime: DS.attr('number'),
+  _endTime: DS.attr('number'),
+  _firstTaskStartTime: DS.attr('number'),
+  _lastTaskFinishTime: DS.attr('number'),
+
+  initTime: Ember.computed("am.initTime", "_initTime",
+    valueComputerFactory("am.initTime", "_initTime")
+  ),
+  startTime: Ember.computed("am.startTime", "_startTime",
+    valueComputerFactory("am.startTime", "_startTime")
+  ),
+  endTime: Ember.computed("am.endTime", "_endTime",
+    valueComputerFactory("am.endTime", "_endTime")
+  ),
+  firstTaskStartTime: Ember.computed("am.firstTaskStartTime", 
"_firstTaskStartTime",
+    valueComputerFactory("am.firstTaskStartTime", "_firstTaskStartTime")
+  ),
+  lastTaskFinishTime: Ember.computed("am.lastTaskFinishTime", 
"_lastTaskFinishTime",
+    valueComputerFactory("am.lastTaskFinishTime", "_lastTaskFinishTime")
+  ),
+
+  totalTasks: DS.attr('number'),
+  _failedTasks: DS.attr('number'),
+  _succeededTasks: DS.attr('number'),
+  _killedTasks: DS.attr('number'),
+
+  failedTasks: Ember.computed("am.failedTasks", "_failedTasks",
+    valueComputerFactory("am.failedTasks", "_failedTasks")
+  ),
+  succeededTasks: Ember.computed("am.succeededTasks", "_succeededTasks",
+    valueComputerFactory("am.succeededTasks", "_succeededTasks")
+  ),
+  killedTasks: Ember.computed("am.killedTasks", "_killedTasks",
+    valueComputerFactory("am.killedTasks", "_killedTasks")
+  ),
+
+  finalStatus: Ember.computed("status", "failedTaskAttempts", function () {
+    var status = this.get("status");
+    if(status === "SUCCEEDED" && this.get("failedTaskAttempts")) {
+      status = "SUCCEEDED_WITH_FAILURES";
+    }
+    return status;
+  }),
+
+  runningTasks: Ember.computed("am.runningTasks", "status", function () {
+    var runningTasks = this.get("am.runningTasks");
+    if(runningTasks === undefined) {
+      runningTasks = this.get("status") === 'SUCCEEDED' ? 0 : null;
+    }
+    return  runningTasks;
+  }),
+  pendingTasks: Ember.computed("totalTasks", "succeededTasks", "runningTasks", 
function () {
+    var pendingTasks = null,
+        runningTasks = this.get("runningTasks"),
+        totalTasks = this.get("totalTasks");
+    if(totalTasks!== null && runningTasks !== null) {
+      pendingTasks = totalTasks - this.get("succeededTasks") - runningTasks;
+    }
+    return pendingTasks;
+  }),
+
+  _failedTaskAttempts: DS.attr('number'),
+  _killedTaskAttempts: DS.attr('number'),
+  failedTaskAttempts: Ember.computed("am.failedTaskAttempts", 
"_failedTaskAttempts",
+    valueComputerFactory("am.failedTaskAttempts", "_failedTaskAttempts")
+  ),
+  killedTaskAttempts: Ember.computed("am.killedTaskAttempts", 
"_killedTaskAttempts",
+    valueComputerFactory("am.killedTaskAttempts", "_killedTaskAttempts")
+  ),
+
+  minDuration: DS.attr('number'),
+  maxDuration: DS.attr('number'),
+  avgDuration: DS.attr('number'),
+
+  firstTasksToStart: DS.attr("object"),
+  lastTasksToFinish: DS.attr("object"),
+  shortestDurationTasks: DS.attr("object"),
+  longestDurationTasks: DS.attr("object"),
+
+  processorClassName: DS.attr('string'),
+
+  dagID: DS.attr('string'),
+  dag: DS.attr('object'), // Auto-loaded by need
+});

Reply via email to