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:37 UTC
[14/53] tez git commit: TEZ-1603. Vertex View for Tez UI. (Sreenath
Somarajapuram via hitesh)
TEZ-1603. Vertex View for Tez UI. (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/ce6d17a9
Tree: http://git-wip-us.apache.org/repos/asf/tez/tree/ce6d17a9
Diff: http://git-wip-us.apache.org/repos/asf/tez/diff/ce6d17a9
Branch: refs/heads/master
Commit: ce6d17a91098303d6f3988d2322b8a93c2c80a89
Parents: 44e5579
Author: Hitesh Shah <hi...@apache.org>
Authored: Mon Oct 27 14:48:12 2014 -0700
Committer: Hitesh Shah <hi...@apache.org>
Committed: Mon Oct 27 14:48:12 2014 -0700
----------------------------------------------------------------------
CHANGES.txt | 2 +
.../scripts/controllers/vertex_controller.js | 40 +++++++
.../controllers/vertex_index_controller.js | 26 +++++
.../controllers/vertex_tasks_controller.js | 106 +++++++++++++++++++
tez-ui/app/scripts/mixins/paginated_content.js | 3 +-
.../app/scripts/models/TimelineRestAdapter.js | 12 ++-
tez-ui/app/scripts/models/dag.js | 12 +++
tez-ui/app/scripts/router.js | 33 +++++-
tez-ui/app/templates/vertex.hbs | 50 +++++++++
tez-ui/app/templates/vertex/counters.hbs | 21 ++++
tez-ui/app/templates/vertex/index.hbs | 81 ++++++++++++++
tez-ui/app/templates/vertex/swimlane.hbs | 22 ++++
tez-ui/app/templates/vertex/tasks.hbs | 46 ++++++++
13 files changed, 449 insertions(+), 5 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/CHANGES.txt
----------------------------------------------------------------------
diff --git a/CHANGES.txt b/CHANGES.txt
index e849248..fcbadcf 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -9,6 +9,8 @@ ALL CHANGES:
TEZ-1634. Fix compressed IFile shuffle errors
TEZ-1615. Skeleton framework for Tez UI
TEZ-1604. Task View for Tez UI
+ TEZ-1603. Vertex View for Tez UI.
+
Release 0.5.2: Unreleased
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_controller.js b/tez-ui/app/scripts/controllers/vertex_controller.js
new file mode 100644
index 0000000..f5c7ef4
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_controller.js
@@ -0,0 +1,40 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+App.VertexController = Em.ObjectController.extend(App.Helpers.DisplayHelper, {
+ controllerName: 'VertexController',
+
+ pageTitle: 'Vertex',
+
+ loading: true,
+
+ updateLoading: function() {
+ this.set('loading', false);
+ }.observes('content'),
+
+ pageSubTitle: function() {
+ return this.get('id');
+ }.property('id'),
+
+ childDisplayViews: [
+ Ember.Object.create({title: 'Details', linkTo: 'vertex.index'}),
+ Ember.Object.create({title: 'Tasks', linkTo: 'vertex.tasks'}),
+ Ember.Object.create({title: 'Counters', linkTo: 'vertex.counters'}),
+ Ember.Object.create({title: 'Swimlane', linkTo: 'vertex.swimlane'}),
+ ],
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_index_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_index_controller.js b/tez-ui/app/scripts/controllers/vertex_index_controller.js
new file mode 100644
index 0000000..c1cf234
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_index_controller.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.
+ */
+
+App.VertexIndexController = Em.ObjectController.extend({
+ controllerName: 'VertexIndexController',
+
+ //TODO: TEZ-1705 : Create a parent class and move this function there to avoid duplication.
+ iconStatus: function() {
+ return App.Helpers.misc.getStatusClassForEntity(this.get('model'));
+ }.property('id', 'status', 'counterGroups'),
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/controllers/vertex_tasks_controller.js b/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
new file mode 100644
index 0000000..05b501c
--- /dev/null
+++ b/tez-ui/app/scripts/controllers/vertex_tasks_controller.js
@@ -0,0 +1,106 @@
+/**
+ * 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.VertexTasksController = Em.ObjectController.extend(App.PaginatedContentMixin, {
+ reloadData: function() {
+ this.loadEntities();
+ }.observes('id'),
+
+ // Required by the PaginatedContentMixin
+ parentEntityType: 'vertex',
+ childEntityType: 'task',
+
+ filterValues: {},
+
+ reloadWhenFiltersChange: function() {
+ var filters = {
+ id: null,
+ primary: {},
+ secondary: {}
+ };
+ var fv = this.filterValues;
+ filters.primary.TEZ_VERTEX_ID = fv.vertex_id;
+ filters.secondary.status = fv.status;
+ this.setFiltersAndLoadEntities(filters);
+ }.observes('filterValues.task_id', 'filterValues.vertex_id', 'filterValues.status'),
+
+ columns: function() {
+ var idCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Task ID',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ "{{#link-to 'task' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+ }),
+ contentPath: 'id',
+ });
+
+ var vertexCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Vertex ID',
+ filterID: 'vertex_id',
+ contentPath: 'vertexID',
+ tableCellViewClass: Em.Table.TableCell.extend({
+ template: Em.Handlebars.compile(
+ "{{#link-to 'vertex' view.cellContent class='ember-table-content'}}{{view.cellContent}}{{/link-to}}")
+ }),
+ });
+
+ var startTimeCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Submission Time',
+ getCellContent: function(row) {
+ return App.Helpers.date.dateFormat(row.get('startTime'));
+ }
+ });
+
+ var endTimeCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'End Time',
+ getCellContent: function(row) {
+ return App.Helpers.date.dateFormat(row.get('endTime'));
+ }
+ });
+
+ var statusCol = App.ExTable.ColumnDefinition.createWithMixins(App.ExTable.FilterColumnMixin,{
+ textAlign: 'text-align-left',
+ headerCellName: 'Status',
+ filterID: 'status',
+ 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 nodeCol = App.ExTable.ColumnDefinition.create({
+ textAlign: 'text-align-left',
+ headerCellName: 'Node',
+ contentPath: 'node'
+ });
+
+ return [idCol, vertexCol, startTimeCol, endTimeCol, statusCol];
+ }.property(),
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/mixins/paginated_content.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/mixins/paginated_content.js b/tez-ui/app/scripts/mixins/paginated_content.js
index 7288759..d34c90e 100644
--- a/tez-ui/app/scripts/mixins/paginated_content.js
+++ b/tez-ui/app/scripts/mixins/paginated_content.js
@@ -18,6 +18,7 @@
var modelToATSType = {
dag: 'TEZ_DAG_ID',
task: 'TEZ_TASK_ID',
+ vertex: 'TEZ_VERTEX_ID',
taskAttempt: 'TEZ_TASK_ATTEMPT_ID'
};
@@ -172,4 +173,4 @@ App.PaginatedContentMixin = Em.Mixin.create({
return params;
},
-});
\ No newline at end of file
+});
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/models/TimelineRestAdapter.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/TimelineRestAdapter.js b/tez-ui/app/scripts/models/TimelineRestAdapter.js
index 43353ba..e753b5e 100644
--- a/tez-ui/app/scripts/models/TimelineRestAdapter.js
+++ b/tez-ui/app/scripts/models/TimelineRestAdapter.js
@@ -275,12 +275,18 @@ var timelineJsonToVertexMap = {
id: 'entity',
name: 'otherinfo.vertexName',
dagID: 'primaryfilters.TEZ_DAG_ID.0',
+ counterGroups: 'counterGroups',
+
startTime: 'otherinfo.startTime',
endTime: 'otherinfo.endTime',
+
status: 'otherinfo.status',
diagnostics: 'otherinfo.diagnostics',
- counterGroups: 'counterGroups',
- numTasks: 'otherinfo.numTasks'
+
+ failedTasks: 'otherinfo.numFailedTasks',
+ sucessfulTasks: 'otherinfo.numSucceededTasks',
+ numTasks: 'otherinfo.numTasks',
+ killedTasks: 'otherinfo.numKilledTasks',
};
App.VertexSerializer = App.TimelineSerializer.extend({
@@ -313,7 +319,7 @@ App.VertexSerializer = App.TimelineSerializer.extend({
}, this);
// delete so that we dont hang on to the json data.
- delete rawPayload.vertex;
+ delete rawPayload.vertices;
return normalizedPayload;
} else {
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/models/dag.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/models/dag.js b/tez-ui/app/scripts/models/dag.js
index 3fc9c83..1bd3182 100644
--- a/tez-ui/app/scripts/models/dag.js
+++ b/tez-ui/app/scripts/models/dag.js
@@ -89,6 +89,7 @@ App.Vertex = DS.Model.extend({
name: DS.attr('string'),
dag: DS.belongsTo('dag'),
+ dagID: DS.attr('string'),
/**
* State of this vertex. Should be one of constants defined in
@@ -146,6 +147,17 @@ App.Vertex = DS.Model.extend({
*/
numTasks: DS.attr('number'),
+ name: DS.attr('string'),
+
+ failedTasks: DS.attr('number'),
+ sucessfulTasks: DS.attr('number'),
+ numTasks: DS.attr('number'),
+ killedTasks: DS.attr('number'),
+
+ diagnostics: DS.attr('string'),
+
+ counterGroups: DS.hasMany('counterGroup'),
+
tasksNumber: function () {
return this.getWithDefault('tasksCount', 0);
}.property('tasksCount'),
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/scripts/router.js
----------------------------------------------------------------------
diff --git a/tez-ui/app/scripts/router.js b/tez-ui/app/scripts/router.js
index 3540495..0e800ac 100644
--- a/tez-ui/app/scripts/router.js
+++ b/tez-ui/app/scripts/router.js
@@ -24,7 +24,13 @@ App.Router.map(function() {
this.route('counters'),
this.route('swimlane')
});
- this.resource('vertex', {path: '/vertex/:vertex_id'});
+
+ this.resource('vertex', {path: '/vertex/:vertex_id'}, function(){
+ this.route('tasks');
+ this.route('counters');
+ this.route('details');
+ this.route('swimlane');
+ });
this.resource('tasks', {path: '/tasks/:dag_id'});
this.resource('task', {path: '/task/:task_id'}, function(){
@@ -141,3 +147,28 @@ App.TaskRoute = Em.Route.extend({
this._super(controller, model);
}
});
+
+App.VertexRoute = Em.Route.extend({
+ model: function(params) {
+ return this.store.find('vertex', params.vertex_id);
+ },
+
+ setupController: function(controller, model) {
+ this._super(controller, model);
+ }
+});
+
+App.VertexSwimlaneRoute = Em.Route.extend({
+ model: function(params) {
+ var model = this.modelFor('vertex');
+ var queryParams = {'primaryFilter': 'TEZ_DAG_ID:' + model.get('dagID') };
+ this.store.unloadAll('task_attempt');
+ return this.store.filter('task_attempt', queryParams, function(ta) {
+ return ta.get('vertexID') == model.id;
+ });
+ },
+
+ setupController: function(controller, model) {
+ this._super(controller, model);
+ }
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex.hbs b/tez-ui/app/templates/vertex.hbs
new file mode 100644
index 0000000..f083e2c
--- /dev/null
+++ b/tez-ui/app/templates/vertex.hbs
@@ -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.
+}}
+
+{{partial "utils/pageHeader"}}
+{{#unless loading}}
+ <div class='margin-small-horizontal'>
+ {{#link-to 'dags'}}
+ <i class='fa-arrow-circle-left fa fa-2x'>
+ <span style='font-size: 85%'> Dags</span>
+ </i>
+ {{/link-to}}
+ </div>
+ <div class='type-table fill-full '>
+ <div class='align-left'>
+ <table class='detail-list'>
+ <tbody>
+ <tr>
+ <td>{{t common.id}}</td>
+ <td>{{id}}</td>
+ </tr>
+ <tr>
+ <td>DAG ID</td>
+ <td>{{dagID}}</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/ce6d17a9/tez-ui/app/templates/vertex/counters.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/counters.hbs b/tez-ui/app/templates/vertex/counters.hbs
new file mode 100644
index 0000000..4c082e1
--- /dev/null
+++ b/tez-ui/app/templates/vertex/counters.hbs
@@ -0,0 +1,21 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you under the Apache License, Version 2.0 (the
+* "License"); you may not use this file except in compliance
+* with the License. You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+}}
+
+<div class='table-container margin-medium' style='width: 50%;'>
+ {{counter-table-component data=counterGroups}}
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/index.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/index.hbs b/tez-ui/app/templates/vertex/index.hbs
new file mode 100644
index 0000000..ce21749
--- /dev/null
+++ b/tez-ui/app/templates/vertex/index.hbs
@@ -0,0 +1,81 @@
+{{!
+* 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>Vertex Name</td>
+ <td>
+ {{name}}
+ </td>
+ </tr>
+ <tr>
+ <td>{{t common.status}}</td>
+ <td>
+ <i {{bind-attr class=':task-status iconStatus'}}></i>
+ {{status}}
+ </td>
+ </tr>
+ <tr>
+ <td>Total Tasks</td>
+ <td>{{numTasks}}</td>
+ </tr>
+ <tr>
+ <td>Successful Tasks</td>
+ <td>{{sucessfulTasks}}</td>
+ </tr>
+ <tr>
+ <td>Failed Tasks</td>
+ <td>
+ {{failedTasks}}
+ </td>
+ </tr>
+ <tr>
+ <td>Killed Tasks</td>
+ <td>{{killedTasks}}</td>
+ </tr>
+ </tbody>
+ </table>
+ </div>
+ <div class='align-right'>
+ <table class='detail-list'>
+ <tbody>
+ <tr>
+ <td>{{t common.time.start}}</td>
+ <td>{{formatUnixTimestamp startTime}}</td>
+ </tr>
+ <tr>
+ <td>{{t common.time.end}}</td>
+ <td>{{formatUnixTimestamp endTime}}</td>
+ </tr>
+ <tr>
+ <td>{{t common.time.duration}}</td>
+ <td>{{formatDuration startTime endTime}}</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
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/swimlane.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/swimlane.hbs b/tez-ui/app/templates/vertex/swimlane.hbs
new file mode 100644
index 0000000..2745e08
--- /dev/null
+++ b/tez-ui/app/templates/vertex/swimlane.hbs
@@ -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.
+}}
+
+<div id="swimlane">
+ {{#view App.SwimlanesView contentBinding="controller.model.content"}}
+ {{/view}}
+</div>
http://git-wip-us.apache.org/repos/asf/tez/blob/ce6d17a9/tez-ui/app/templates/vertex/tasks.hbs
----------------------------------------------------------------------
diff --git a/tez-ui/app/templates/vertex/tasks.hbs b/tez-ui/app/templates/vertex/tasks.hbs
new file mode 100644
index 0000000..eac99a1
--- /dev/null
+++ b/tez-ui/app/templates/vertex/tasks.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-left'>
+ {{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
+ filtersBinding='filterValues'
+ hasFilter=true
+ }}
+ </div>
+{{else}}
+ {{partial 'utils/loadingSpinner'}}
+{{/unless}}
\ No newline at end of file