You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tez.apache.org by je...@apache.org on 2014/12/10 04:33:51 UTC
[28/53] tez git commit: TEZ-1741. App view. (Sreenath Somarajapuram
via hitesh)
TEZ-1741. App view. (Sreenath Somarajapuram via hitesh)
Project: http://git-wip-us.apache.org/repos/asf/tez/repo
Commit: http://git-wip-us.apache.org/repos/asf/tez/commit/28ef6ec8
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/28ef6ec8
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/28ef6ec8
Branch: refs/heads/master
Commit: 28ef6ec8f134552f2030cd8b507fe50fc7dee019
Parents: b4be9ca
Author: Hitesh Shah <hi...@apache.org>
Authored: Mon Nov 10 22:01:29 2014 -0800
Committer: Hitesh Shah <hi...@apache.org>
Committed: Mon Nov 10 22:01:29 2014 -0800
----------------------------------------------------------------------
CHANGES.txt | 1 +
tez-ui/src/main/webapp/app/scripts/app.js | 12 +-
.../app/scripts/controllers/dags_controller.js | 12 +-
.../controllers/tez-app-configs-controller.js | 89 ++++++++++++
.../scripts/controllers/tez-app-controller.js | 41 ++++++
.../controllers/tez-app-dags-controller.js | 138 +++++++++++++++++++
.../app/scripts/models/TimelineRestAdapter.js | 95 ++++++++++++-
.../src/main/webapp/app/scripts/models/dag.js | 39 ++++++
tez-ui/src/main/webapp/app/scripts/router.js | 61 +++++++-
.../src/main/webapp/app/templates/tez-app.hbs | 43 ++++++
.../webapp/app/templates/tez-app/configs.hbs | 46 +++++++
.../main/webapp/app/templates/tez-app/dags.hbs | 46 +++++++
.../main/webapp/app/templates/tez-app/index.hbs | 80 +++++++++++
13 files changed, 693 insertions(+), 10 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index 9073a5e..9cc4e82 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -13,6 +13,7 @@ ALL CHANGES:
TEZ-1720. Allow filters in all tables and also to pass in filters using url params.
TEZ-1708. Make UI part of TEZ build process.
TEZ-1617. Shim layer for Tez UI for use within Ambari.
+ TEZ-1741. App view.
Release 0.5.2: Unreleased
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/app.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/app.js b/tez-ui/src/main/webapp/app/scripts/app.js
index 2db916b..d735bcc 100644
--- a/tez-ui/src/main/webapp/app/scripts/app.js
+++ b/tez-ui/src/main/webapp/app/scripts/app.js
@@ -28,7 +28,8 @@ var App = window.App = Em.Application.createWithMixins(Bootstrap, {
env: {
standalone: window.parent === window,
- timelineBaseUrl: "http://localhost:8188"
+ timelineBaseUrl: "http://localhost:8188",
+ RMWebUrl: "http://localhost:8088"
}
});
@@ -46,6 +47,15 @@ Ember.Application.initializer({
host: App.env.timelineBaseUrl
});
application.ApplicationSerializer = App.TimelineSerializer.extend();
+
+ application.AppDetailAdapter = DS.RESTAdapter.extend({
+ namespace: 'ws/v1/applicationhistory',
+ host: App.env.timelineBaseUrl,
+ pathForType: function() {
+ return "apps";
+ },
+ });
+
}
});
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
index 896db7f..6887bce 100644
--- a/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/dags_controller.js
@@ -144,7 +144,17 @@ App.DagsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
}
}
});
- var appIdCol = columnHelper('Application ID', 'applicationId');
+ var appIdCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Application ID',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ "{{#link-to 'tez-app' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+ }),
+ getCellContent: function(row) {
+ return row.get('applicationId')
+ }
+ });
return [nameCol, idCol, userCol, statusCol, submittedTimeCol, runTimeCol, appIdCol];
}.property(),
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
new file mode 100644
index 0000000..6843733
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-configs-controller.js
@@ -0,0 +1,89 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.TezAppConfigsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+ needs: "tezApp",
+ count: 10,
+
+ key: null,
+ value: null,
+
+ loadEntities: function() {
+ var that = this,
+ count = 0,
+ filter = this.getFilterProperties(),
+ configs = configs = this.get('configs').content,
+ filtered = [],
+ i = 0;
+
+ if(filter.fromId) {
+ while(i < configs.length && configs[i].id != filter.fromId) {
+ i++;
+ }
+ }
+
+ // Filter the available data
+ for(; i < configs.length && filtered.length < filter.limit; i++){
+ if((that.key === null || configs[i].get('key').indexOf(that.key) !=-1) && (that.value === null || configs[i].get('value').indexOf(that.value) != -1)) {
+ filtered.push(configs[i]);
+ }
+ }
+
+ this.set('entities', filtered);
+ this.set('loading', false);
+ },
+
+ loadData: function() {
+ var filters = {
+ primary: {
+ key: this.key,
+ value: this.value
+ },
+ };
+ this.setFiltersAndLoadEntities(filters);
+ },
+
+ actions : {
+ filterUpdated: function(filterID, value) {
+ // any validations required goes here.
+ if (!!value) {
+ this.set(filterID, value);
+ } else {
+ this.set(filterID, null);
+ }
+ this.loadData();
+ }
+ },
+
+ columns: function() {
+ var columnHelper = function(displayText, columnId) {
+ return App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin, {
+ textAlign: 'text-align-left',
+ headerCellName: displayText,
+ filterID: columnId,
+ contentPath: columnId
+ });
+ }
+
+ return [
+ columnHelper("Conf key", 'key'),
+ columnHelper("Conf value", 'value'),
+ ];
+ }.property(),
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.js
new file mode 100644
index 0000000..74e985c
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-controller.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.
+ */
+
+App.TezAppController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
+ controllerName: 'AppController',
+
+ pageTitle: 'App',
+
+ loading: true,
+
+ RMWebUrl: App.env.RMWebUrl,
+
+ updateLoading: function() {
+ this.set('loading', false);
+ }.observes('content'),
+
+ pageSubTitle: function() {
+ return this.get('id');
+ }.property('id'),
+
+ childDisplayViews: [
+ Ember.Object.create({title: 'Details', linkTo: 'tez-app.index'}),
+ Ember.Object.create({title: 'Dags', linkTo: 'tez-app.dags'}),
+ Ember.Object.create({title: 'Configs', linkTo: 'tez-app.configs'}),
+ ],
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
new file mode 100644
index 0000000..d07478c
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/scripts/controllers/tez-app-dags-controller.js
@@ -0,0 +1,138 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.TezAppDagsController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+ needs: "tezApp",
+
+ // required by the PaginatedContentMixin
+ childEntityType: 'dag',
+
+ queryParams: {
+ status_filter: 'status',
+ user_filter: 'user'
+ },
+ status_filter: null,
+ user_filter: null,
+
+ loadData: function() {
+ console.log(new Error().stack);
+ var filters = {
+ primary: {
+ applicationId: this.get('appId'),
+ user: this.user_filter
+ },
+ secondary: {
+ status: this.status_filter
+ }
+ };
+ this.setFiltersAndLoadEntities(filters);
+ },
+
+ actions : {
+ filterUpdated: function(filterID, value) {
+ // any validations required goes here.
+ if (!!value) {
+ this.set(filterID, value);
+ } else {
+ this.set(filterID, null);
+ }
+ this.loadData();
+ }
+ },
+
+ /* table view for dags */
+ columns: function() {
+ var columnHelper = function(columnName, valName) {
+ return App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: columnName,
+ contentPath: valName
+ });
+ }
+
+ var nameCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Dag Name',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ "{{#link-to 'dag' view.cellContent.id class='ember-table-content'}}{{view.cellContent.name}}{{/link-to}}")
+ }),
+ getCellContent: function(row) {
+ return {
+ id: row.get('id'),
+ name: row.get('name')
+ };
+ }
+ });
+ var idCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Dag ID',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ "{{#link-to 'dag' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+ }),
+ getCellContent: function(row) {
+ return row.get('id')
+ }
+ });
+ var userCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin, {
+ textAlign: 'text-align-left',
+ headerCellName: 'Submitter',
+ filterID: 'user_filter',
+ contentPath: 'user'
+ });
+ var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
+ textAlign: 'text-align-left',
+ headerCellName: 'Status',
+ filterID: 'status_filter',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ '<span class="ember-table-content"> \
+ <i {{bind-attr class=":task-status view.cellContent.statusIcon"}}></i>\
+ {{view.cellContent.status}}</span>')
+ }),
+ getCellContent: function(row) {
+ return {
+ status: row.get('status'),
+ statusIcon: App.Helpers.misc.getStatusClassForEntity(row)
+ };
+ }
+ });
+ var submittedTimeCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Submitted Time',
+ getCellContent: function(row) {
+ return App.Helpers.date.dateFormat(row.get('submittedTime'));
+ }
+ });
+ var runTimeCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Run Time',
+ getCellContent: function(row) {
+ var st = row.get('startTime');
+ var et = row.get('endTime');
+ console.log(st, et);
+ if (st && et) {
+ return App.Helpers.date.durationSummary(st, et);
+ }
+ }
+ });
+ return [nameCol, idCol, userCol, statusCol, submittedTimeCol, runTimeCol];
+ }.property(),
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
index f29b467..468b906 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/TimelineRestAdapter.js
@@ -16,10 +16,11 @@
*/
var typeToPathMap = {
- dag: 'TEZ_DAG_ID',
- vertex: 'TEZ_VERTEX_ID',
+ dag: 'TEZ_DAG_ID',
+ vertex: 'TEZ_VERTEX_ID',
task: 'TEZ_TASK_ID',
- taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
+ taskAttempt: 'TEZ_TASK_ATTEMPT_ID',
+ tezApp: 'TEZ_APPLICATION'
};
App.TimelineRESTAdapter = DS.RESTAdapter.extend({
@@ -330,3 +331,91 @@ App.VertexSerializer = App.TimelineSerializer.extend({
return Em.JsonMapper.map(hash, timelineJsonToVertexMap);
},
});
+
+var timelineJsonToAppDetailMap = {
+ id: 'appId',
+ attemptId: 'currentAppAttemptId',
+
+ name: 'name',
+ queue: 'queue',
+ user: 'user',
+ type: 'type',
+
+ startedTime: 'startedTime',
+ elapsedTime: 'elapsedTime',
+ finishedTime: 'finishedTime',
+ submittedTime: 'submittedTime',
+
+ appState: 'appState',
+
+ finalAppStatus: 'finalAppStatus',
+ diagnostics: 'otherinfo.diagnostics',
+};
+
+App.AppDetailSerializer = App.TimelineSerializer.extend({
+ normalize: function(type, hash, prop) {
+ return Em.JsonMapper.map(hash, timelineJsonToAppDetailMap);
+ },
+});
+
+var timelineJsonToTezAppMap = {
+ id: 'entity',
+
+ appId: 'appId',
+
+ entityType: 'entitytype',
+
+ startedTime: 'startedTime',
+ domain: 'domain',
+
+ dags: 'relatedentities.TEZ_DAG_ID',
+ configs: 'configs'
+};
+
+App.TezAppSerializer = App.TimelineSerializer.extend({
+ _normalizeSinglePayload: function(rawPayload){
+ var configs = rawPayload.otherinfo.config,
+ appId = rawPayload.entity.substr(4),
+ kVData = [],
+ id;
+
+ rawPayload.appId = appId;
+ rawPayload.configs = [];
+
+ for(var key in configs) {
+ id = appId + key;
+ rawPayload.configs.push(id);
+ kVData.push({
+ id: id,
+ key: key,
+ value: configs[key]
+ });
+ }
+
+ return {
+ tezApp: rawPayload,
+ kVData: kVData
+ };
+ },
+ normalizePayload: function(rawPayload) {
+ if (!!rawPayload.tezApps) {
+ var normalizedPayload = {
+ tezApps: [],
+ kVData: []
+ },
+ push = Array.prototype.push;
+ rawPayload.tezApps.forEach(function(app){
+ var n = this._normalizeSinglePayload(app);
+ normalizedPayload.tezApps.push(n.tezApp);
+ push.apply(normalizedPayload.kVData,n.kVData);
+ });
+ return normalizedPayload;
+ }
+ else {
+ return this._normalizeSinglePayload(rawPayload.tezApp)
+ }
+ },
+ normalize: function(type, hash, prop) {
+ return Em.JsonMapper.map(hash, timelineJsonToTezAppMap);
+ },
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/models/dag.js b/tez-ui/src/main/webapp/app/scripts/models/dag.js
index 1bd3182..2dbb0d7 100644
--- a/tez-ui/src/main/webapp/app/scripts/models/dag.js
+++ b/tez-ui/src/main/webapp/app/scripts/models/dag.js
@@ -217,6 +217,40 @@ App.Vertex = DS.Model.extend({
}.property('duration')
});
+App.AppDetail = DS.Model.extend({
+ attemptId: DS.attr('string'),
+
+ user: DS.attr('string'),
+ name: DS.attr('string'),
+ queue: DS.attr('string'),
+ type: DS.attr('string'),
+
+ appState: DS.attr('string'),
+ finalAppStatus: DS.attr('string'),
+ progress: DS.attr('string'),
+
+ startedTime: DS.attr('number'),
+ elapsedTime: DS.attr('number'),
+ finishedTime: DS.attr('number'),
+ submittedTime: DS.attr('number'),
+
+ diagnostics: DS.attr('string'),
+});
+
+App.TezApp = DS.Model.extend({
+ appId: DS.attr('string'),
+ entityType: DS.attr('string'),
+ domain: DS.attr('string'),
+
+ startedTime: DS.attr('number'),
+
+ appDetail: DS.belongsTo('appDetail', { async: true }),
+ dags: DS.hasMany('dag', { async: true }),
+
+ configs: DS.hasMany('kVData', { async: false })
+});
+
+
App.Task = App.AbstractEntity.extend({
status: DS.attr('status'),
@@ -235,6 +269,11 @@ App.Task = App.AbstractEntity.extend({
counterGroups: DS.hasMany('counterGroup', { inverse: 'parent' })
});
+App.KVDatum = DS.Model.extend({
+ key: DS.attr('string'),
+ value: DS.attr('string'),
+});
+
App.VertexState = {
NEW: "NEW",
INITIALIZING: "INITIALIZING",
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/scripts/router.js b/tez-ui/src/main/webapp/app/scripts/router.js
index c2bcca8..5da59db 100644
--- a/tez-ui/src/main/webapp/app/scripts/router.js
+++ b/tez-ui/src/main/webapp/app/scripts/router.js
@@ -19,12 +19,17 @@
App.Router.map(function() {
this.resource('dags', { path: '/' });
this.resource('dag', { path: '/dag/:dag_id'}, function() {
- this.route('vertices'),
- this.route('tasks'),
- this.route('counters'),
- this.route('swimlane')
+ this.route('vertices');
+ this.route('tasks');
+ this.route('counters');
+ this.route('swimlane');
});
+ this.resource('tez-app', {path: '/tez-app/:app_id'}, function(){
+ this.route('dags');
+ this.route('configs');
+ });
+
this.resource('vertex', {path: '/vertex/:vertex_id'}, function(){
this.route('tasks');
this.route('counters');
@@ -226,4 +231,50 @@ App.TaskAttemptsRoute = Em.Route.extend({
this._super(controller, model);
controller.loadData();
}
-});
\ No newline at end of file
+});
+
+App.TezAppRoute = Em.Route.extend({
+ model: function(params) {
+ var store = this.store;
+ return store.find('tezApp', 'tez_' + params.app_id).then(function(tezApp){
+ return store.find('appDetail', tezApp.get('appId')).then(function(appDetails){
+ tezApp.set('appDetail', appDetails);
+ return tezApp;
+ });
+ });
+ },
+});
+
+App.TezAppDagsRoute = Em.Route.extend({
+ queryParams: {
+ count: {
+ refreshModel: true,
+ replace: true
+ },
+ fromID: {
+ refreshModel: true,
+ replace: true
+ },
+ user: {
+ refreshModel: true,
+ replace: true
+ },
+ status: {
+ refreshModel: true,
+ replace: true
+ }
+ },
+
+ setupController: function(controller, model) {
+ this._super(controller, model);
+ controller.loadData();
+ }
+});
+
+App.TezAppConfigsRoute = Em.Route.extend({
+ setupController: function(controller, model) {
+ this._super(controller, model);
+ controller.loadData();
+ }
+});
+
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/templates/tez-app.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/tez-app.hbs b/tez-ui/src/main/webapp/app/templates/tez-app.hbs
new file mode 100644
index 0000000..e4fba4e
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/tez-app.hbs
@@ -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.
+}}
+
+{{partial "utils/pageHeader"}}
+{{#unless loading}}
+ <div class='type-table fill-full '>
+ <div class='align-left'>
+ <table class='detail-list'>
+ <tbody>
+ <tr>
+ <td>App Id</td>
+ <td><a href="{{unbound RMWebUrl}}/cluster/app/tez_{{unbound id}}">{{unbound id}}</a></td>
+ </tr>
+ <tr>
+ <td>Attempt Id</td>
+ <td>{{appDetail.attemptId}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class='pill-container align-right'>
+ {{bs-pills contentBinding='childDisplayViews' selectedBinding='childDisplayViewSelected' size='lg'}}
+ </div>
+ </div>
+ {{outlet}}
+{{else}}
+ {{partial 'utils/loadingSpinner'}}
+{{/unless}}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs b/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
new file mode 100644
index 0000000..4662279
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/tez-app/configs.hbs
@@ -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.
+}}
+
+{{#unless loading}}
+ <div class='margin-small'>
+ <span class='align-right'>
+ {{page-nav-component
+ hasPrev=hasPrev
+ hasNext=hasNext
+ navNext='navigateNext'
+ navPrev='navigatePrev'
+ navFirst='navigateFirst'
+ }}
+ </span>
+ <div class='align-clear'> </div>
+ </div>
+
+ <div class='table-container'>
+ {{extended-table-component
+ hasFooter=false
+ enableContentSelection=true
+ columnsBinding="columns"
+ contentBinding="sortedContent"
+ forceFillColumns=true
+ hasFilter=true
+ onFilterUpdated='filterUpdated'
+ }}
+ </div>
+{{else}}
+ {{partial 'utils/loadingSpinner'}}
+{{/unless}}
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/templates/tez-app/dags.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/tez-app/dags.hbs b/tez-ui/src/main/webapp/app/templates/tez-app/dags.hbs
new file mode 100644
index 0000000..4662279
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/tez-app/dags.hbs
@@ -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.
+}}
+
+{{#unless loading}}
+ <div class='margin-small'>
+ <span class='align-right'>
+ {{page-nav-component
+ hasPrev=hasPrev
+ hasNext=hasNext
+ navNext='navigateNext'
+ navPrev='navigatePrev'
+ navFirst='navigateFirst'
+ }}
+ </span>
+ <div class='align-clear'> </div>
+ </div>
+
+ <div class='table-container'>
+ {{extended-table-component
+ hasFooter=false
+ enableContentSelection=true
+ columnsBinding="columns"
+ contentBinding="sortedContent"
+ forceFillColumns=true
+ hasFilter=true
+ onFilterUpdated='filterUpdated'
+ }}
+ </div>
+{{else}}
+ {{partial 'utils/loadingSpinner'}}
+{{/unless}}
http://git-wip-us.apache.org/repos/asf/tez/blob/28ef6ec8/tez-ui/src/main/webapp/app/templates/tez-app/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/src/main/webapp/app/templates/tez-app/index.hbs b/tez-ui/src/main/webapp/app/templates/tez-app/index.hbs
new file mode 100644
index 0000000..90a335b
--- /dev/null
+++ b/tez-ui/src/main/webapp/app/templates/tez-app/index.hbs
@@ -0,0 +1,80 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class='type-table fill-full margin-small-horizontal'>
+ <div class='align-left'>
+ <table class='detail-list'>
+ <tbody>
+ <tr>
+ <td>App Name</td>
+ <td>
+ {{appDetail.name}}
+ </td>
+ </tr>
+ <tr>
+ <td>Queue</td>
+ <td>
+ {{appDetail.queue}}
+ </td>
+ </tr>
+ <tr>
+ <td>User</td>
+ <td>{{appDetail.user}}</td>
+ </tr>
+ <tr>
+ <td>Type</td>
+ <td>{{appDetail.type}}</td>
+ </tr>
+ <tr>
+ <td>App State</td>
+ <td>
+ {{appDetail.appState}}
+ </td>
+ </tr>
+ <tr>
+ <td>Final App Status</td>
+ <td>{{appDetail.finalAppStatus}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class='align-right'>
+ <table class='detail-list'>
+ <tbody>
+ <tr>
+ <td>{{t common.time.start}}</td>
+ <td>{{formatUnixTimestamp appDetail.startedTime}}</td>
+ </tr>
+ <tr>
+ <td>{{t common.time.end}}</td>
+ <td>{{formatUnixTimestamp appDetail.finishedTime}}</td>
+ </tr>
+ <tr>
+ <td>{{t common.time.duration}}</td>
+ <td>{{formatDuration appDetail.startedTime appDetail.finishedTime}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+</div>
+
+{{#if diagnostics}}
+ {{#bs-panel heading="Diagnostics" collapsible=false dismiss=false type='danger'}}
+ {{formatDiagnostics diagnostics}}
+ {{/bs-panel}}
+{{/if}}
\ No newline at end of file