YARN-5153. Add a toggle button to switch between timeline view / table view for containers and application-attempts in new YARN UI. Contributed by Akhil PB.
This commit is contained in:
parent
5d38504071
commit
443aa51bc1
@ -19,11 +19,4 @@
|
||||
import Ember from 'ember';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
nodeHttpAddressFormatted: Ember.computed('attempt.nodeHttpAddress', function() {
|
||||
var nodeHttpAddress = this.get('attempt.nodeHttpAddress');
|
||||
if (nodeHttpAddress && nodeHttpAddress.indexOf('://') < 0) {
|
||||
nodeHttpAddress = 'http://' + nodeHttpAddress;
|
||||
}
|
||||
return nodeHttpAddress;
|
||||
})
|
||||
});
|
||||
|
@ -18,6 +18,7 @@
|
||||
|
||||
import Ember from 'ember';
|
||||
import Converter from 'yarn-ui/utils/converter';
|
||||
import ColumnDef from 'em-table/utils/column-definition';
|
||||
|
||||
export default Ember.Component.extend({
|
||||
canvas: {
|
||||
@ -31,6 +32,8 @@ export default Ember.Component.extend({
|
||||
modelArr: [],
|
||||
colors: d3.scale.category10().range(),
|
||||
_selected: undefined,
|
||||
gridColumns: [],
|
||||
gridRows: [],
|
||||
|
||||
selected: function() {
|
||||
return this._selected;
|
||||
@ -276,5 +279,199 @@ export default Ember.Component.extend({
|
||||
if (this.modelArr.length > 0) {
|
||||
this.setSelected(this.modelArr[0]);
|
||||
}
|
||||
|
||||
if (this.get('attemptModel')) {
|
||||
this.setAttemptsGridColumnsAndRows();
|
||||
} else {
|
||||
this.setContainersGridColumnsAndRows();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
setAttemptsGridColumnsAndRows: function() {
|
||||
var self = this;
|
||||
var columns = [];
|
||||
|
||||
columns.push({
|
||||
id: 'id',
|
||||
headerTitle: 'Attempt ID',
|
||||
contentPath: 'id',
|
||||
cellComponentName: 'em-table-linked-cell',
|
||||
minWidth: '300px',
|
||||
getCellContent: function(row) {
|
||||
return {
|
||||
displayText: row.get('id'),
|
||||
routeName: 'yarn-app-attempt',
|
||||
id: row.get('id')
|
||||
};
|
||||
}
|
||||
}, {
|
||||
id: 'attemptStartedTime',
|
||||
headerTitle: 'Started Time',
|
||||
contentPath: 'attemptStartedTime'
|
||||
}, {
|
||||
id: 'finishedTime',
|
||||
headerTitle: 'Finished Time',
|
||||
contentPath: 'finishedTime',
|
||||
getCellContent: function(row) {
|
||||
if (row.get('finishedTs')) {
|
||||
return row.get('finishedTime');
|
||||
}
|
||||
return 'N/A';
|
||||
}
|
||||
}, {
|
||||
id: 'elapsedTime',
|
||||
headerTitle: 'Elapsed Time',
|
||||
contentPath: 'elapsedTime'
|
||||
}, {
|
||||
id: 'appMasterContainerId',
|
||||
headerTitle: 'AM Container ID',
|
||||
contentPath: 'appMasterContainerId',
|
||||
minWidth: '300px'
|
||||
}, {
|
||||
id: 'amNodeId',
|
||||
headerTitle: 'AM Node ID',
|
||||
contentPath: 'amNodeId'
|
||||
}, {
|
||||
id: 'attemptState',
|
||||
headerTitle: 'State',
|
||||
contentPath: 'attemptState',
|
||||
getCellContent: function(row) {
|
||||
var state = row.get('attemptState');
|
||||
if (state) {
|
||||
return state;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 'nodeHttpAddress',
|
||||
headerTitle: 'NodeManager Web UI',
|
||||
contentPath: 'nodeHttpAddress',
|
||||
cellComponentName: 'em-table-html-cell',
|
||||
getCellContent: function(row) {
|
||||
var address = self.checkHttpProtocol(row.get('nodeHttpAddress'));
|
||||
if (address) {
|
||||
return `<a href="${address}" target="_blank">${address}</a>`;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 'logsLink',
|
||||
headerTitle: 'Logs',
|
||||
contentPath: 'logsLink',
|
||||
cellComponentName: 'em-table-html-cell',
|
||||
getCellContent: function(row) {
|
||||
var logUrl = self.checkHttpProtocol(row.get('logsLink'));
|
||||
if (logUrl) {
|
||||
return `<a href="${logUrl}" target="_blank">Link</a>`;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var gridCols = ColumnDef.make(columns);
|
||||
this.set('gridColumns', gridCols);
|
||||
this.set('gridRows', this.modelArr);
|
||||
},
|
||||
|
||||
setContainersGridColumnsAndRows: function() {
|
||||
var self = this;
|
||||
var columns = [];
|
||||
|
||||
columns.push({
|
||||
id: 'id',
|
||||
headerTitle: 'Container ID',
|
||||
contentPath: 'id',
|
||||
minWidth: '300px'
|
||||
}, {
|
||||
id: 'startedTime',
|
||||
headerTitle: 'Started Time',
|
||||
contentPath: 'startedTime'
|
||||
}, {
|
||||
id: 'finishedTime',
|
||||
headerTitle: 'Finished Time',
|
||||
contentPath: 'finishedTime',
|
||||
getCellContent: function(row) {
|
||||
if (row.get('finishedTs')) {
|
||||
return row.get('finishedTime');
|
||||
}
|
||||
return 'N/A';
|
||||
}
|
||||
}, {
|
||||
id: 'elapsedTime',
|
||||
headerTitle: 'Elapsed Time',
|
||||
contentPath: 'elapsedTime'
|
||||
}, {
|
||||
id: 'priority',
|
||||
headerTitle: 'Priority',
|
||||
contentPath: 'priority'
|
||||
}, {
|
||||
id: 'containerExitStatus',
|
||||
headerTitle: 'Exit Status',
|
||||
contentPath: 'containerExitStatus',
|
||||
getCellContent: function(row) {
|
||||
var status = row.get('containerExitStatus');
|
||||
if (status) {
|
||||
return status;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 'containerState',
|
||||
headerTitle: 'State',
|
||||
contentPath: 'containerState',
|
||||
getCellContent: function(row) {
|
||||
var state = row.get('containerState');
|
||||
if (state) {
|
||||
return state;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 'logUrl',
|
||||
headerTitle: 'Logs',
|
||||
contentPath: 'logUrl',
|
||||
cellComponentName: 'em-table-html-cell',
|
||||
getCellContent: function(row) {
|
||||
var url = self.checkHttpProtocol(row.get('logUrl'));
|
||||
if (url) {
|
||||
return `<a href="${url}" target="_blank">${url}</a>`;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
}, {
|
||||
id: 'nodeHttpAddress',
|
||||
headerTitle: 'Node Manager UI',
|
||||
contentPath: 'nodeHttpAddress',
|
||||
cellComponentName: 'em-table-html-cell',
|
||||
getCellContent: function(row) {
|
||||
var address = self.checkHttpProtocol(row.get('nodeHttpAddress'));
|
||||
if (address) {
|
||||
return `<a href="${address}" target="_blank">${address}</a>`;
|
||||
} else {
|
||||
return 'N/A';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var gridCols = ColumnDef.make(columns);
|
||||
this.set('gridColumns', gridCols);
|
||||
this.set('gridRows', this.modelArr);
|
||||
},
|
||||
|
||||
checkHttpProtocol: function(prop) {
|
||||
if (prop && prop.indexOf('://') < 0) {
|
||||
prop = 'http://' + prop;
|
||||
}
|
||||
return prop;
|
||||
},
|
||||
|
||||
isDataEmpty: Ember.computed(function() {
|
||||
return this.modelArr.length === 0;
|
||||
})
|
||||
});
|
||||
|
@ -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 Ember from 'ember';
|
||||
|
||||
export function prependProtocol(params/*, hash*/) {
|
||||
let address = params[0];
|
||||
if (address && address.indexOf('://') < 0) {
|
||||
address = 'http://' + address;
|
||||
}
|
||||
return address;
|
||||
}
|
||||
|
||||
export default Ember.Helper.helper(prependProtocol);
|
@ -23,39 +23,43 @@
|
||||
<td>{{attempt.id}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Start Time</td>
|
||||
<td>Started Time</td>
|
||||
<td>{{attempt.attemptStartedTime}}</td>
|
||||
</tr>
|
||||
{{#if attempt.validatedFinishedTs}}
|
||||
<tr>
|
||||
<td>Finished Time</td>
|
||||
<td>{{attempt.validatedFinishedTs}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
<tr>
|
||||
<td>Elapsed Time</td>
|
||||
<td>{{attempt.elapsedTime}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>AM Container Id</td>
|
||||
<td>{{attempt.appMasterContainerId}}</td>
|
||||
</tr>
|
||||
{{#if attempt.IsAmNodeUrl}}
|
||||
<tr>
|
||||
<td>AM Node Web UI</td>
|
||||
<td><a href="{{nodeHttpAddressFormatted}}" target="_blank">{{nodeHttpAddressFormatted}}</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
<tr>
|
||||
<td>AM Node Id</td>
|
||||
<td>{{attempt.amNodeId}}</td>
|
||||
</tr>
|
||||
{{#if attempt.IsLinkAvailable}}
|
||||
<tr>
|
||||
<td>Log</td>
|
||||
<td><a href="{{attempt.logsLink}}" target="_blank">Link</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if attempt.attemptState}}
|
||||
<tr>
|
||||
<td>Attempt State</td>
|
||||
<td>{{attempt.attemptState}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if attempt.elapsedTime}}
|
||||
{{#if attempt.nodeHttpAddress}}
|
||||
<tr>
|
||||
<td>Elapsed Time</td>
|
||||
<td>{{attempt.elapsedTime}}</td>
|
||||
<td>AM Node Web UI</td>
|
||||
<td><a href="{{prepend-protocol attempt.nodeHttpAddress}}" target="_blank">{{attempt.nodeHttpAddress}}</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if attempt.logsLink}}
|
||||
<tr>
|
||||
<td>Log</td>
|
||||
<td><a href="{{prepend-protocol attempt.logsLink}}" target="_blank">Link</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
|
@ -19,13 +19,15 @@
|
||||
<table id="container-table" class="table table-striped table-bordered" cellspacing="0" width="100%" height="100%">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>Start Time</td>
|
||||
<td>Started Time</td>
|
||||
<td>{{container.startedTime}}</td>
|
||||
</tr>
|
||||
{{#if container.validatedFinishedTs}}
|
||||
<tr>
|
||||
<td>Finished Time</td>
|
||||
<td>{{container.validatedFinishedTs}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
<tr>
|
||||
<td>Elapsed Time</td>
|
||||
<td>{{container.elapsedTime}}</td>
|
||||
@ -34,21 +36,29 @@
|
||||
<td>Priority</td>
|
||||
<td>{{container.priority}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Log</td>
|
||||
<td><a href="{{container.logUrl}}" target="_blank">Link</a></td>
|
||||
</tr>
|
||||
{{#if container.containerExitStatus}}
|
||||
<tr>
|
||||
<td>Exit Status</td>
|
||||
<td>{{container.containerExitStatus}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if container.containerState}}
|
||||
<tr>
|
||||
<td>State</td>
|
||||
<td>{{container.containerState}}</td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if container.nodeHttpAddress}}
|
||||
<tr>
|
||||
<td>NodeManager UI</td>
|
||||
<td><a href="{{container.nodeHttpAddress}}" target="_blank">{{container.nodeHttpAddress}}</a></td>
|
||||
<td><a href="{{prepend-protocol container.nodeHttpAddress}}" target="_blank">{{container.nodeHttpAddress}}</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
{{#if container.logUrl}}
|
||||
<tr>
|
||||
<td>Log</td>
|
||||
<td><a href="{{prepend-protocol container.logUrl}}" target="_blank">Link</a></td>
|
||||
</tr>
|
||||
{{/if}}
|
||||
</tbody>
|
||||
</table>
|
||||
|
@ -25,30 +25,49 @@
|
||||
Containers
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
<br/><br/>
|
||||
<div class="col-md-8 container-fluid" id={{parent-id}}>
|
||||
</div>
|
||||
|
||||
<!-- diag info -->
|
||||
<div class="col-md-4 container-fluid">
|
||||
<div class="panel panel-default add-ellipsis">
|
||||
<div class="panel-heading">
|
||||
{{#if selected.link}}
|
||||
{{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}}
|
||||
{{else}}
|
||||
{{selected.id}}
|
||||
{{/if}}
|
||||
{{#if isDataEmpty}}
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="active">
|
||||
<a href="#graphViewTab" role="tab" data-toggle="tab">Graph View</a>
|
||||
</li>
|
||||
<li class="">
|
||||
<a href="#gridViewTab" role="tab" data-toggle="tab">Grid View</a>
|
||||
</li>
|
||||
</ul>
|
||||
<div class="panel-body">
|
||||
<div class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="graphViewTab">
|
||||
<br/><br/>
|
||||
<div class="col-md-8 container-fluid" id={{parent-id}}></div>
|
||||
<!-- diag info -->
|
||||
<div class="col-md-4 container-fluid">
|
||||
<div class="panel panel-default add-ellipsis">
|
||||
<div class="panel-heading">
|
||||
{{#if selected.link}}
|
||||
{{#link-to selected.linkname selected.id}}{{selected.id}}{{/link-to}}
|
||||
{{else}}
|
||||
{{selected.id}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if attemptModel}}
|
||||
{{app-attempt-table attempt=selected}}
|
||||
{{else}}
|
||||
{{container-table container=selected}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div role="tabpanel" class="tab-pane" id="gridViewTab">
|
||||
{{em-table columns=gridColumns rows=gridRows}}
|
||||
</div>
|
||||
{{#if attemptModel}}
|
||||
{{app-attempt-table attempt=selected}}
|
||||
{{else}}
|
||||
{{container-table container=selected}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel-body">
|
||||
<h4 class="text-center">No data available!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{outlet}}
|
||||
{{outlet}}
|
||||
|
@ -0,0 +1,28 @@
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { prependProtocol } from '../../../helpers/prepend-protocol';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Helper | prepend protocol');
|
||||
|
||||
// Replace this with your real tests.
|
||||
test('it works', function(assert) {
|
||||
let result = prependProtocol(42);
|
||||
assert.ok(result);
|
||||
});
|
Loading…
Reference in New Issue
Block a user