YARN-5335. Use em-table in app/nodes pages for new YARN UI. Contributed by Sunil G.

This commit is contained in:
Sunil G 2017-02-28 13:49:19 +05:30
parent f187d63816
commit ef488044d0
26 changed files with 492 additions and 66 deletions

View File

@ -25,9 +25,7 @@ export default AbstractAdapter.extend({
urlForQuery(query/*, modelName*/) { urlForQuery(query/*, modelName*/) {
var url = this._buildURL(); var url = this._buildURL();
if (query.state) { url = url + '/apps';
url = url + '/apps/?state=' + query.state;
}
return url; return url;
}, },

View File

@ -36,7 +36,6 @@ export default BaseUsageDonutChart.extend({
value: v.toFixed(2) value: v.toFixed(2)
}); });
console.log(v);
avail = avail - v; avail = avail - v;
} }
}.bind(this)); }.bind(this));

View File

@ -54,7 +54,6 @@ export default BaseChartComponent.extend({
// 50 is for title // 50 is for title
var outerRadius = (h - 50 - 2 * layout.margin) / 2; var outerRadius = (h - 50 - 2 * layout.margin) / 2;
var innerRadius = outerRadius * 0.618; var innerRadius = outerRadius * 0.618;
console.log("inner:" + innerRadius + " outer:" + outerRadius);
var arc = d3.svg.arc() var arc = d3.svg.arc()
.innerRadius(innerRadius) .innerRadius(innerRadius)

View File

@ -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 Ember from 'ember';
import ColumnDef from 'em-table/utils/column-definition';
export default Ember.Controller.extend({
columns: function() {
var colums = [];
colums.push({
id: 'appId',
headerTitle: 'Application ID',
contentPath: 'id',
cellComponentName: 'em-table-linked-cell',
getCellContent: function(row) {
return {
displayText: row.id,
routeName: 'yarn-app',
id: row.id
};
},
minWidth: "250px"
}, {
id: 'appType',
headerTitle: 'Application Type',
contentPath: 'applicationType',
}, {
id: 'appName',
headerTitle: 'Application Name',
contentPath: 'appName',
}, {
id: 'appUsr',
headerTitle: 'User',
contentPath: 'user',
minWidth: "50px"
}, {
id: 'queue',
headerTitle: 'Queue',
contentPath: 'queue',
}, {
id: 'state',
headerTitle: 'State',
contentPath: 'state',
cellComponentName: 'em-table-status-cell',
minWidth: "50px"
}, {
id: 'progress',
headerTitle: 'Progress',
contentPath: 'progress',
cellComponentName: 'em-table-progress-cell',
cellDefinition: {
valueMax: 100
},
}, {
id: 'stTime',
headerTitle: 'Start Time',
contentPath: 'startTime',
}, {
id: 'elTime',
headerTitle: 'Elapsed Time',
contentPath: 'elapsedTime',
cellDefinition: {
type: "duration"
}
}, {
id: 'finishTime',
headerTitle: 'Finished Time',
contentPath: 'validatedFinishedTs',
observePath: true
}, {
id: 'priority',
headerTitle: 'Priority',
contentPath: 'priority',
}, {
id: 'cluster',
headerTitle: '%Cluster',
contentPath: 'clusterUsagePercentage',
observePath: true
});
return ColumnDef.make(colums);
}.property()
});

View File

@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Ember from 'ember';
import ColumnDef from 'em-table/utils/column-definition';
import AppTableController from '../app-table-columns';
export default AppTableController.extend({
});

View File

@ -0,0 +1,25 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Ember from 'ember';
import ColumnDef from 'em-table/utils/column-definition';
import AppTableController from '../app-table-columns';
export default AppTableController.extend({
});

View File

@ -20,8 +20,9 @@ import Ember from 'ember';
export default Ember.Controller.extend({ export default Ember.Controller.extend({
breadcrumbs: Ember.computed("model.attempt.appId", function () { breadcrumbs: Ember.computed("model.nodeInfo", function () {
var nodeInfo = this.get("model.nodeInfo"); var nodeInfo = this.get("model.nodeInfo");
return [{ return [{
text: "Home", text: "Home",
routeName: 'application' routeName: 'application'

View File

@ -0,0 +1,109 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import Ember from 'ember';
import ColumnDef from 'em-table/utils/column-definition';
export default Ember.Controller.extend({
columns: function() {
var colums = [];
colums.push({
id: 'label',
headerTitle: 'Node Label',
contentPath: 'nodeLabelsAsString',
minWidth: "100px"
}, {
id: 'rack',
headerTitle: 'Rack',
contentPath: 'rack',
minWidth: "100px"
}, {
id: 'state',
headerTitle: 'Node State',
contentPath: 'state',
cellComponentName: 'em-table-status-cell',
minWidth: "100px"
}, {
id: 'address',
headerTitle: 'Node Address',
contentPath: 'id',
minWidth: "300px"
}, {
id: 'nodeId',
headerTitle: 'Node HTTP Address',
contentPath: 'nodeHTTPAddress',
cellComponentName: 'em-table-linked-cell',
getCellContent: function(row) {
var node_id = row.get("id"),
node_addr = row.get("nodeHTTPAddress"),
href = `#/yarn-node/${node_id}/${node_addr}`;
switch(row.get("nodeState")) {
case "SHUTDOWN":
case "LOST":
href = "";
}
return {
text: row.get("nodeHTTPAddress"),
href: href
};
},
minWidth: "250px"
}, {
id: 'containers',
headerTitle: 'Containers',
contentPath: 'numContainers',
}, {
id: 'memUsed',
headerTitle: 'Mem Used',
contentPath: 'usedMemoryBytes',
cellDefinition: {
type: "memory"
}
}, {
id: 'memAvail',
headerTitle: 'Mem Available',
contentPath: 'availMemoryBytes',
cellDefinition: {
type: "memory"
}
}, {
id: 'coresUsed',
headerTitle: 'VCores Used',
contentPath: 'usedVirtualCores',
}, {
id: 'coresAvail',
headerTitle: 'VCores Available',
contentPath: 'availableVirtualCores',
}, {
id: 'healthUpdate',
headerTitle: 'Last Health Update',
contentPath: 'lastHealthUpdate',
}, {
id: 'healthReport',
headerTitle: 'Health-Report',
contentPath: 'healthReport',
}, {
id: 'version',
headerTitle: 'Version',
contentPath: 'version',
observePath: true
});
return ColumnDef.make(colums);
}.property()
});

View File

@ -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 Ember from 'ember';
import TableDefinition from 'em-table/utils/table-definition';
import AppTableController from '../app-table-columns';
export default AppTableController.extend({
// Your custom instance of table definition
tableDefinition: TableDefinition.create(),
// Search text alias, any change in controller's searchText would affect the table's searchText, and vice-versa.
_selectedObserver: Ember.on("init", Ember.observer("model.selected", function () {
this.set("tableDefinition.searchText", this.get("model.selected"));
})),
});

View File

@ -96,4 +96,12 @@ export default DS.Model.extend({
"<p>Used Memory: " + Math.round(this.get("usedMemoryMB")) + ' MB</p>' + "<p>Used Memory: " + Math.round(this.get("usedMemoryMB")) + ' MB</p>' +
"<p>Available Memory: " + Math.round(this.get("availMemoryMB")) + ' MB</p>'; "<p>Available Memory: " + Math.round(this.get("availMemoryMB")) + ' MB</p>';
}.property(), }.property(),
usedMemoryBytes: function() {
return this.get("usedMemoryMB") * 1024 * 1024;
}.property("usedMemoryMB"),
availMemoryBytes: function() {
return this.get("availMemoryMB") * 1024 * 1024;
}.property("availMemoryMB"),
}); });

View File

@ -23,13 +23,11 @@ import AbstractRoute from './abstract';
export default AbstractRoute.extend({ export default AbstractRoute.extend({
model() { model() {
return Ember.RSVP.hash({ return Ember.RSVP.hash({
apps: this.store.findAll('yarn-app', {reload: true}),
clusterMetrics: this.store.findAll('ClusterMetric', {reload: true}), clusterMetrics: this.store.findAll('ClusterMetric', {reload: true}),
}); });
}, },
unloadAll() { unloadAll() {
this.store.unloadAll('yarn-app');
this.store.unloadAll('ClusterMetric'); this.store.unloadAll('ClusterMetric');
} }
}); });

View File

@ -19,4 +19,13 @@
import Ember from 'ember'; import Ember from 'ember';
export default Ember.Route.extend({ export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
apps: this.store.findAll('yarn-app', {reload: true}),
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
}
}); });

View File

@ -19,4 +19,15 @@
import Ember from 'ember'; import Ember from 'ember';
export default Ember.Route.extend({ export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
apps: this.store.query('yarn-app', {
applicationTypes: "org-apache-slider"
}),
});
},
unloadAll() {
this.store.unloadAll('yarn-app');
}
}); });

View File

@ -26,7 +26,9 @@ export default AbstractRoute.extend({
selected : param.queue_name, selected : param.queue_name,
queues: this.store.query('yarn-queue', {}), queues: this.store.query('yarn-queue', {}),
selectedQueue : undefined, selectedQueue : undefined,
apps: this.store.findAll('yarn-app', {reload: true}) apps: this.store.query('yarn-app', {
queue: param.queue_name
})
}); });
}, },

View File

@ -31,8 +31,7 @@ export default AbstractRoute.extend({
return Ember.RSVP.hash({ return Ember.RSVP.hash({
selected : queueName, selected : queueName,
queues: this.store.query('yarn-queue', {}), queues: this.store.query('yarn-queue', {}),
selectedQueue : undefined, selectedQueue : undefined
apps: this.store.findAll('yarn-app', {reload: true})
}); });
}, },

View File

@ -43,7 +43,8 @@ export default DS.JSONAPISerializer.extend({
queue: payload.queue, queue: payload.queue,
state: payload.state, state: payload.state,
startTime: Converter.timeStampToDate(payload.startedTime), startTime: Converter.timeStampToDate(payload.startedTime),
elapsedTime: Converter.msToElapsedTime(payload.elapsedTime), //elapsedTime: Converter.msToElapsedTime(payload.elapsedTime),
elapsedTime: payload.elapsedTime,
finishedTime: Converter.timeStampToDate(payload.finishedTime), finishedTime: Converter.timeStampToDate(payload.finishedTime),
finalStatus: payload.finalStatus, finalStatus: payload.finalStatus,
progress: payload.progress, progress: payload.progress,

View File

@ -16,9 +16,12 @@
limitations under the License. limitations under the License.
--}} --}}
{{#if model.apps}} {{#if model.apps.isPending}}
{{app-table table-id="apps-table" arr=model.apps}} <h4 align="center">Loading...</h4>
{{simple-table table-id="apps-table" bFilter=true colsOrder="0,desc" colTypes="natural elapsed-time" colTargets="0 7"}}
{{else}} {{else}}
{{#if model.apps}}
{{em-table columns=columns rows=model.apps}}
{{else}}
<h4 align="center">Could not find any applications from this cluster</h4> <h4 align="center">Could not find any applications from this cluster</h4>
{{/if}}
{{/if}} {{/if}}

View File

@ -17,9 +17,7 @@
--}} --}}
{{#if model.apps}} {{#if model.apps}}
{{app-table table-id="apps-table" arr=model.apps}} {{em-table columns=columns rows=model.apps}}
{{simple-table table-id="apps-table" bFilter=true colsOrder="0,desc"
colTypes="natural elapsed-time" colTargets="0 7" defaultSearch="slider"}}
{{else}} {{else}}
<h4 align="center">Could not find any applications from this cluster</h4> <h4 align="center">Could not find any applications from this cluster</h4>
{{/if}} {{/if}}

View File

@ -18,47 +18,7 @@
<div class="row"> <div class="row">
{{#if model.nodes}} {{#if model.nodes}}
<table id="nodes-table" class="display table table-striped table-bordered" {{em-table columns=columns rows=model.nodes}}
cellspacing="0" width="100%">
<thead>
<tr>
<th>Node Labels</th>
<th>Rack</th>
<th>Node State</th>
<th>Node Address</th>
<th>Node HTTP Address</th>
<th>Last Health Update</th>
<th>Health-Report</th>
<th>Containers</th>
<th>Mem Used</th>
<th>Mem Avail</th>
<th>VCores Used</th>
<th>VCores Avail</th>
<th>Version</th>
</tr>
</thead>
<tbody>
{{#each model.nodes as |node|}}
<tr>
<td>{{node.nodeLabelsAsString}}</td>
<td>{{node.rack}}</td>
<td><span class={{node.nodeStateStyle}}>{{node.state}}</span></td>
<td>{{node.id}}</td>
{{node-link nodeId=node.id nodeHTTPAddress=node.nodeHTTPAddress nodeState=node.state}}
<td>{{node.lastHealthUpdate}}</td>
<td>{{node.healthReport}}</td>
<td>{{node.numContainers}}</td>
<td>{{divide num=node.usedMemoryMB den=1024}} GB</td>
<td>{{divide num=node.availMemoryMB den=1024}} GB</td>
<td>{{node.usedVirtualCores}}</td>
<td>{{node.availableVirtualCores}}</td>
<td>{{node.version}}</td>
</tr>
{{/each}}
</tbody>
</table>
{{simple-table table-id="nodes-table" bFilter=true}}
{{else}} {{else}}
<h4 align="center">No nodes found on this cluster</h4> <h4 align="center">No nodes found on this cluster</h4>
{{/if}} {{/if}}

View File

@ -19,8 +19,7 @@
<div class="row"> <div class="row">
<div class="col-lg-12 container-fluid"> <div class="col-lg-12 container-fluid">
{{#if model.apps}} {{#if model.apps}}
{{app-table table-id="apps-table" arr=model.apps}} {{em-table columns=columns rows=model.apps}}
{{simple-table table-id="apps-table" bFilter=true colTypes="elapsed-time" colTargets="7"}}
{{else}} {{else}}
<h4 align = "center">Could not find any applications from this cluster</h4> <h4 align = "center">Could not find any applications from this cluster</h4>
{{/if}} {{/if}}

View File

@ -20,9 +20,9 @@
"devDependencies": { "devDependencies": {
"broccoli-asset-rev": "2.4.2", "broccoli-asset-rev": "2.4.2",
"broccoli-funnel": "1.0.1", "broccoli-funnel": "1.0.1",
"em-table": "0.1.6", "em-table": "0.7.0",
"ember-bootstrap": "0.5.1",
"ember-array-contains-helper": "1.0.2", "ember-array-contains-helper": "1.0.2",
"ember-bootstrap": "0.5.1",
"ember-cli": "1.13.13", "ember-cli": "1.13.13",
"ember-cli-app-version": "1.0.0", "ember-cli-app-version": "1.0.0",
"ember-cli-babel": "5.1.6", "ember-cli-babel": "5.1.6",
@ -47,6 +47,9 @@
"select2": "4.0.0" "select2": "4.0.0"
}, },
"dependencies": { "dependencies": {
"em-helpers": "^0.5.13" "em-helpers": "^0.8.0",
"em-table": "^0.7.0",
"ember-cli-moment-shim": "^3.0.1",
"ember-cli-numeral": "^0.2.0"
} }
} }

View File

@ -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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:app-table-columns', 'Unit | Controller | app table columns', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-apps/apps', 'Unit | Controller | yarn apps/apps', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-apps/services', 'Unit | Controller | yarn apps/services', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-nodes/table', 'Unit | Controller | yarn nodes/table', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});

View File

@ -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 { moduleFor, test } from 'ember-qunit';
moduleFor('controller:yarn-queue/apps', 'Unit | Controller | yarn queue/apps', {
// Specify the other units that are required for this test.
// needs: ['controller:foo']
});
// Replace this with your real tests.
test('it exists', function(assert) {
let controller = this.subject();
assert.ok(controller);
});