YARN-7445. Render Applications and Services page with filters in new YARN UI. Contributed by Vasudevan Skm.

This commit is contained in:
Sunil G 2017-11-13 19:41:49 +05:30
parent 3e26077848
commit fb62bd625f
16 changed files with 250 additions and 155 deletions

3
.gitignore vendored
View File

@ -44,3 +44,6 @@ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/dist
hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/tmp hadoop-yarn-project/hadoop-yarn/hadoop-yarn-ui/tmp
yarnregistry.pdf yarnregistry.pdf
patchprocess/ patchprocess/
.history/

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';
export default Ember.Component.extend({
content: null,
classNames: ["em-table-simple-status-cell"],
statusName: Ember.computed("content", function () {
var status = this.get("content");
return status.toLowerCase().capitalize();
}),
});

View File

@ -34,7 +34,8 @@ export default Ember.Controller.extend({
headerTitle: 'Application ID', headerTitle: 'Application ID',
contentPath: 'id', contentPath: 'id',
cellComponentName: 'em-table-linked-cell', cellComponentName: 'em-table-linked-cell',
minWidth: "250px", minWidth: "280px",
facetType: null,
getCellContent: function(row) { getCellContent: function(row) {
return { return {
displayText: row.id, displayText: row.id,
@ -45,30 +46,33 @@ export default Ember.Controller.extend({
id: 'appType', id: 'appType',
headerTitle: 'Application Type', headerTitle: 'Application Type',
contentPath: 'applicationType', contentPath: 'applicationType',
facetType: null,
}, { }, {
id: 'appName', id: 'appName',
headerTitle: 'Application Name', headerTitle: 'Application Name',
contentPath: 'appName', contentPath: 'appName',
facetType: null,
}, { }, {
id: 'appUsr', id: 'appUsr',
headerTitle: 'User', headerTitle: 'User',
contentPath: 'user', contentPath: 'user',
minWidth: "50px" minWidth: "50px"
}, {
id: 'queue',
headerTitle: 'Queue',
contentPath: 'queue',
}, { }, {
id: 'state', id: 'state',
headerTitle: 'State', headerTitle: 'State',
contentPath: 'state', contentPath: 'state',
cellComponentName: 'em-table-status-cell', cellComponentName: 'em-table-simple-status-cell',
minWidth: "50px" minWidth: "50px"
}, {
id: 'queue',
headerTitle: 'Queue',
contentPath: 'queue',
}, { }, {
id: 'progress', id: 'progress',
headerTitle: 'Progress', headerTitle: 'Progress',
contentPath: 'progress', contentPath: 'progress',
cellComponentName: 'em-table-progress-cell', cellComponentName: 'em-table-progress-cell',
facetType: null,
cellDefinition: { cellDefinition: {
valueMax: 100 valueMax: 100
} }
@ -76,10 +80,12 @@ export default Ember.Controller.extend({
id: 'stTime', id: 'stTime',
headerTitle: 'Start Time', headerTitle: 'Start Time',
contentPath: 'startTime', contentPath: 'startTime',
facetType: null,
}, { }, {
id: 'elTime', id: 'elTime',
headerTitle: 'Elapsed Time', headerTitle: 'Elapsed Time',
contentPath: 'elapsedTime', contentPath: 'elapsedTime',
facetType: null,
cellDefinition: { cellDefinition: {
type: "duration" type: "duration"
} }
@ -87,6 +93,7 @@ export default Ember.Controller.extend({
id: 'finishTime', id: 'finishTime',
headerTitle: 'Finished Time', headerTitle: 'Finished Time',
contentPath: 'validatedFinishedTs', contentPath: 'validatedFinishedTs',
facetType: null,
observePath: true observePath: true
}, { }, {
id: 'priority', id: 'priority',
@ -108,6 +115,7 @@ export default Ember.Controller.extend({
headerTitle: 'Service Name', headerTitle: 'Service Name',
contentPath: 'appName', contentPath: 'appName',
minWidth: "200px", minWidth: "200px",
facetType: null,
cellComponentName: 'em-table-linked-cell', cellComponentName: 'em-table-linked-cell',
getCellContent: function(row) { getCellContent: function(row) {
return { return {
@ -119,22 +127,25 @@ export default Ember.Controller.extend({
id: 'appId', id: 'appId',
headerTitle: 'Application ID', headerTitle: 'Application ID',
contentPath: 'id', contentPath: 'id',
facetType: null,
minWidth: "250px" minWidth: "250px"
}, { }, {
id: 'state', id: 'state',
headerTitle: 'State', headerTitle: 'State',
contentPath: 'state', contentPath: 'state',
cellComponentName: 'em-table-status-cell', cellComponentName: 'em-table-simple-status-cell',
minWidth: "50px" minWidth: "50px"
}, { }, {
id: 'cluster', id: 'cluster',
headerTitle: '%Cluster', headerTitle: '%Cluster',
contentPath: 'clusterUsagePercentage', contentPath: 'clusterUsagePercentage',
facetType: null,
observePath: true observePath: true
}, { }, {
id: 'elTime', id: 'elTime',
headerTitle: 'Elapsed Time', headerTitle: 'Elapsed Time',
contentPath: 'elapsedTime', contentPath: 'elapsedTime',
facetType: null,
cellDefinition: { cellDefinition: {
type: "duration" type: "duration"
}, },
@ -143,6 +154,7 @@ export default Ember.Controller.extend({
id: 'appUsr', id: 'appUsr',
headerTitle: 'User', headerTitle: 'User',
contentPath: 'user', contentPath: 'user',
facetType: null,
minWidth: "50px" minWidth: "50px"
}, { }, {
id: 'queue', id: 'queue',
@ -152,10 +164,12 @@ export default Ember.Controller.extend({
id: 'stTime', id: 'stTime',
headerTitle: 'Started Time', headerTitle: 'Started Time',
contentPath: 'startTime', contentPath: 'startTime',
facetType: null,
}, { }, {
id: 'finishTime', id: 'finishTime',
headerTitle: 'Finished Time', headerTitle: 'Finished Time',
contentPath: 'validatedFinishedTs', contentPath: 'validatedFinishedTs',
facetType: null,
observePath: true observePath: true
}); });
return ColumnDef.make(colums); return ColumnDef.make(colums);

View File

@ -22,7 +22,10 @@ import AppTableController from '../app-table-columns';
export default AppTableController.extend({ export default AppTableController.extend({
queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'], queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'],
tableDefinition: TableDefinition.create(), tableDefinition: TableDefinition.create({
enableFaceting: true,
rowCount: 25
}),
searchText: Ember.computed.alias('tableDefinition.searchText'), searchText: Ember.computed.alias('tableDefinition.searchText'),
sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'), sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'),
sortOrder: Ember.computed.alias('tableDefinition.sortOrder'), sortOrder: Ember.computed.alias('tableDefinition.sortOrder'),

View File

@ -24,7 +24,9 @@ export default AppTableController.extend({
queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'], queryParams: ['searchText', 'sortColumnId', 'sortOrder', 'pageNum', 'rowCount'],
tableDefinition: TableDefinition.create({ tableDefinition: TableDefinition.create({
sortColumnId: 'stTime', sortColumnId: 'stTime',
sortOrder: 'desc' sortOrder: 'desc',
rowCount: 25,
enableFaceting: true
}), }),
searchText: Ember.computed.alias('tableDefinition.searchText'), searchText: Ember.computed.alias('tableDefinition.searchText'),
sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'), sortColumnId: Ember.computed.alias('tableDefinition.sortColumnId'),

View File

@ -19,7 +19,6 @@
body, html, body > .ember-view { body, html, body > .ember-view {
height: 100%; height: 100%;
overflow: visible; overflow: visible;
color: @text-color;
background: #f6f6f8; background: #f6f6f8;
font-family: "Open Sans","Helvetica Neue", sans-serif!important; font-family: "Open Sans","Helvetica Neue", sans-serif!important;
} }
@ -419,29 +418,44 @@ div.attempt-info-panel table > tbody > tr > td:last-of-type {
display: inline-block; display: inline-block;
} }
.yarn-cluster-status i { .yarn-cluster-status i,
.em-table-simple-status-cell i{
display: inline-block; display: inline-block;
border-radius: 100%;
border: 1px solid;
}
.yarn-cluster-status i {
width: 12px; width: 12px;
height: 12px; height: 12px;
border-radius: 10px;
border: 1px solid;
margin: 3px; margin: 3px;
vertical-align: bottom; vertical-align: bottom;
} }
.yarn-cluster-status i.started { .em-table-simple-status-cell i {
width: 10px;
height: 10px;
margin: 3px 3px 3px 0;
vertical-align: text-bottom;
}
.yarn-cluster-status i.started,
.em-table-simple-status-cell i.finished {
border-color: #43b135; border-color: #43b135;
background-color: #60cea5; background-color: #60cea5;
} }
.yarn-cluster-status i.stopped { .yarn-cluster-status i.stopped,
.em-table-simple-status-cell i.killed {
border-color: #b04b4e; border-color: #b04b4e;
background-color: #ef6162; background-color: #ef6162;
} }
.yarn-cluster-status i.inited{ .yarn-cluster-status i.inited,
.em-table-simple-status-cell i.running {
border-color: #1c95c0; border-color: #1c95c0;
background-color: #26bbf0; background-color: #26bbf0;
} }
.yarn-cluster-status i.notinited { .yarn-cluster-status i.notinited,
.em-table-simple-status-cell i.accepted {
border-color: #dca41b; border-color: #dca41b;
background-color: #ffbc0b; background-color: #ffbc0b;
} }
@ -630,3 +644,74 @@ div.service-action-mask img {
left: 45% !important; left: 45% !important;
z-index: 9999; z-index: 9999;
} }
.yarn-applications-container .table-panel-left .em-table-facet-panel {
width: 240px;
margin-right: 15px;
padding: 0 0 15px 0;
background: none;
border: none;
border-radius: 0;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .field-list > li .em-table-facet-panel-values{
margin-top: 0px;
margin-bottom: -4px;
background: #fff;
border: 1px solid #d5d5d5;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .field-name {
background-color: #f7f7f7;
border-bottom: 1px solid #d5d5d5;
padding: 10px 15px;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .all-button {
right: 5px !important;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .field-name::before {
margin-right: 5px;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .value-list {
padding: 0 10px;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .filter-box {
padding: 5px;
margin: 5px 0;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .more-less {
padding: 5px 0;
}
.yarn-applications-container .table-panel-left .em-table-facet-panel .field-list {
padding-top: 0px;
}
.yarn-applications-container .em-table .table-column .table-header-cell {
padding: 7.5px 0 7.5px 7.5px;
}
.yarn-applications-container .ember-view.table-cell {
padding: 10px 15px;
height: auto;
}
.yarn-applications-container .resize-column {
position: absolute;
right: -14px;
display: inline-block;
padding: 10px 0;
top: -36px;
font-size: 42px;
line-height: 2em;
}
.em-table .table-column .table-header-cell {
background-color: #f7f7f7;
border-bottom: 1px solid #d5d5d5;
}

View File

@ -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.
}}
{{#if content}}
<span>
<i class={{lower content}} />
{{statusName}}
</span>
{{else}}
<span class="txt-message"> N/A </span>
{{/if}}

View File

@ -18,68 +18,8 @@
{{breadcrumb-bar breadcrumbs=breadcrumbs}} {{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid"> <div class="col-md-12 container-fluid yarn-applications-container">
<div class="row">
<div class="col-md-2 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Applications
</div>
<div class="panel-body">
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
<ul class="nav nav-pills nav-stacked collapse in">
{{#link-to 'yarn-apps.apps' tagName="li"}}
{{#link-to 'yarn-apps.apps'}}All Applications{{/link-to}}
{{/link-to}}
</ul>
</ul>
</div>
</div>
</div>
<div class="col-md-10 container-fluid">
{{#if model.clusterMetrics}}
<div class="row">
<div class="col-lg-4 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Finished Apps
</div>
<div class="container-fluid" id="finishedapps-donut-chart">
{{donut-chart data=model.clusterMetrics.firstObject.getFinishedAppsDataForDonutChart
showLabels=true
parentId="finishedapps-donut-chart"
ratio=0.6
maxHeight=350
colorTargets="good warn error"
}}
</div>
</div>
</div>
<div class="col-lg-4 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Running Apps
</div>
<div class="container-fluid" id="runningapps-donut-chart">
{{donut-chart data=model.clusterMetrics.firstObject.getRunningAppsDataForDonutChart
showLabels=true
parentId="runningapps-donut-chart"
ratio=0.6
maxHeight=350
colorTargets="warn good"
}}
</div>
</div>
</div>
</div>
{{/if}}
<div class="row"> <div class="row">
{{outlet}} {{outlet}}
</div> </div>
</div>
</div>
</div> </div>

View File

@ -18,72 +18,10 @@
{{breadcrumb-bar breadcrumbs=breadcrumbs}} {{breadcrumb-bar breadcrumbs=breadcrumbs}}
<div class="col-md-12 container-fluid yarn-applications-container">
<div class="col-md-12 container-fluid">
<div class="row">
<div class="col-md-2 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Services
</div>
<div class="panel-body">
<ul class="nav nav-pills nav-stacked" id="stacked-menu">
<ul class="nav nav-pills nav-stacked collapse in">
{{#link-to 'yarn-services' tagName="li"}}
{{#link-to 'yarn-services'}}Long Running Services{{/link-to}}
{{/link-to}}
</ul>
</ul>
</div>
</div>
</div>
<div class="col-md-10 container-fluid">
<div class="row">
<div class="col-lg-4 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Finished Services
</div>
<div class="container-fluid" id="finishedapps-donut-chart">
{{donut-chart data=getFinishedServicesDataForDonutChart
showLabels=true
parentId="finishedapps-donut-chart"
ratio=0.6
maxHeight=350
colorTargets="good warn error"
}}
</div>
</div>
</div>
<div class="col-lg-4 container-fluid">
<div class="panel panel-default">
<div class="panel-heading">
Running Services
</div>
<div class="container-fluid" id="runningapps-donut-chart">
{{donut-chart data=getRunningServicesDataForDonutChart
showLabels=true
parentId="runningapps-donut-chart"
ratio=0.6
maxHeight=350
colorTargets="warn good"
}}
</div>
</div>
</div>
<div class="col-lg-4 container-fluid">
<a class="btn btn-primary pull-right" href="#/yarn-deploy-service">New Service</a>
</div>
</div>
{{#if model.apps}} {{#if model.apps}}
{{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}} {{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}}
{{else}} {{else}}
<h4 align="center">Could not find any services from this cluster</h4> <h4 align="center">Could not find any services from this cluster</h4>
{{/if}} {{/if}}
</div>
</div>
</div> </div>

View File

@ -21,6 +21,7 @@
"spin.js": "~2.3.2", "spin.js": "~2.3.2",
"momentjs": "~2.10.6", "momentjs": "~2.10.6",
"select2": "4.0.0", "select2": "4.0.0",
"snippet-ss": "~1.11.0" "snippet-ss": "~1.11.0",
"alasql": "^0.4.3"
} }
} }

View File

@ -38,7 +38,6 @@ module.exports = function(environment) {
'connect-src': "* 'self'", 'connect-src': "* 'self'",
'child-src': "'self' 'unsafe-inline'", 'child-src': "'self' 'unsafe-inline'",
'style-src': "'self' 'unsafe-inline'", 'style-src': "'self' 'unsafe-inline'",
'script-src': "'self' 'unsafe-inline'"
} }
}; };

View File

@ -49,6 +49,7 @@ module.exports = function(defaults) {
app.import('bower_components/bootstrap/dist/css/bootstrap.css'); app.import('bower_components/bootstrap/dist/css/bootstrap.css');
app.import('bower_components/bootstrap/dist/css/bootstrap-theme.css'); app.import('bower_components/bootstrap/dist/css/bootstrap-theme.css');
app.import('bower_components/bootstrap/dist/js/bootstrap.min.js'); app.import('bower_components/bootstrap/dist/js/bootstrap.min.js');
app.import('bower_components/alasql/dist/alasql.js');
// Use `app.import` to add additional libraries to the generated // Use `app.import` to add additional libraries to the generated
// output files. // output files.

View File

@ -2,5 +2,13 @@
"compilerOptions": { "compilerOptions": {
"target": "ES6", "target": "ES6",
"module": "commonjs" "module": "commonjs"
} },
"exclude": [
"node_modules",
"dist",
"bower_components",
"jspm_packages",
"tmp",
"temp"
]
} }

View File

@ -56,6 +56,6 @@
}, },
"dependencies": { "dependencies": {
"em-helpers": "^0.8.0", "em-helpers": "^0.8.0",
"em-table": "^0.7.0" "em-table": "0.11.3"
} }
} }

View File

@ -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 { moduleForComponent, test } from 'ember-qunit';
import hbs from 'htmlbars-inline-precompile';
moduleForComponent('em-table-simple-status-cell', 'Integration | Component | em table simple status cell', {
integration: true
});
test('it renders', function(assert) {
// Set any properties with this.set('myProperty', 'value');
// Handle any actions with this.on('myAction', function(val) { ... });" + EOL + EOL +
this.render(hbs`{{em-table-simple-status-cell}}`);
assert.equal(this.$().text().trim(), '');
// Template block usage:" + EOL +
this.render(hbs`
{{#em-table-simple-status-cell}}
template block text
{{/em-table-simple-status-cell}}
`);
assert.equal(this.$().text().trim(), 'template block text');
});

View File

@ -1402,9 +1402,9 @@ em-helpers@^0.8.0:
optionalDependencies: optionalDependencies:
phantomjs-prebuilt "2.1.13" phantomjs-prebuilt "2.1.13"
em-table@^0.7.0: em-table@0.11.3:
version "0.7.2" version "0.11.3"
resolved "https://registry.yarnpkg.com/em-table/-/em-table-0.7.2.tgz#867ff734701df9765f2505e02acd74768edb0f71" resolved "https://registry.yarnpkg.com/em-table/-/em-table-0.11.3.tgz#20e605cc3814214e644199399a2383cee8d23eeb"
dependencies: dependencies:
ember-cli-htmlbars "^1.0.1" ember-cli-htmlbars "^1.0.1"
ember-cli-less "^1.4.0" ember-cli-less "^1.4.0"