YARN-7499. Layout changes to Application details page in new YARN UI. Contributed by Vasudevan Skm.
This commit is contained in:
parent
0ea182d0fa
commit
641ba5c7a1
|
@ -39,7 +39,7 @@ export default Ember.Controller.extend({
|
|||
getCellContent: function(row) {
|
||||
return {
|
||||
displayText: row.id,
|
||||
href: `#/yarn-app/${row.id}/info`
|
||||
href: `#/yarn-app/${row.id}/attempts`
|
||||
};
|
||||
}
|
||||
}, {
|
||||
|
@ -120,7 +120,7 @@ export default Ember.Controller.extend({
|
|||
getCellContent: function(row) {
|
||||
return {
|
||||
displayText: row.get('appName'),
|
||||
href: `#/yarn-app/${row.id}/info?service=${row.get('appName')}`
|
||||
href: `#/yarn-app/${row.id}/attempts?service=${row.get('appName')}`
|
||||
};
|
||||
}
|
||||
}, {
|
||||
|
|
|
@ -32,6 +32,65 @@ export default Ember.Controller.extend({
|
|||
text: 'App'
|
||||
}],
|
||||
|
||||
actions: {
|
||||
showStopServiceConfirm() {
|
||||
this.set('actionResponse', null);
|
||||
Ember.$("#stopServiceConfirmDialog").modal('show');
|
||||
},
|
||||
|
||||
stopService() {
|
||||
var self = this;
|
||||
Ember.$("#stopServiceConfirmDialog").modal('hide');
|
||||
var adapter = this.store.adapterFor('yarn-servicedef');
|
||||
self.set('isLoading', true);
|
||||
adapter.stopService(this.model.serviceName).then(function () {
|
||||
self.set('actionResponse', { msg: 'Service stopped successfully. Auto refreshing in 5 seconds.', type: 'success' });
|
||||
Ember.run.later(self, function () {
|
||||
this.set('actionResponse', null);
|
||||
this.send("refresh");
|
||||
}, 5000);
|
||||
}, function (errr) {
|
||||
let messg = errr.diagnostics || 'Error: Stop service failed!';
|
||||
self.set('actionResponse', { msg: messg, type: 'error' });
|
||||
}).finally(function () {
|
||||
self.set('isLoading', false);
|
||||
});
|
||||
},
|
||||
|
||||
showDeleteServiceConfirm() {
|
||||
this.set('actionResponse', null);
|
||||
Ember.$("#deleteServiceConfirmDialog").modal('show');
|
||||
},
|
||||
|
||||
deleteService() {
|
||||
var self = this;
|
||||
Ember.$("#deleteServiceConfirmDialog").modal('hide');
|
||||
var adapter = this.store.adapterFor('yarn-servicedef');
|
||||
self.set('isLoading', true);
|
||||
adapter.deleteService(this.model.serviceName).then(function () {
|
||||
self.set('actionResponse', { msg: 'Service deleted successfully. Redirecting to services in 5 seconds.', type: 'success' });
|
||||
Ember.run.later(self, function () {
|
||||
this.set('actionResponse', null);
|
||||
this.transitionToRoute("yarn-services");
|
||||
}, 5000);
|
||||
}, function (errr) {
|
||||
let messg = errr.diagnostics || 'Error: Delete service failed!';
|
||||
self.set('actionResponse', { msg: messg, type: 'error' });
|
||||
}).finally(function () {
|
||||
self.set('isLoading', false);
|
||||
});
|
||||
},
|
||||
|
||||
resetActionResponse() {
|
||||
this.set('actionResponse', null);
|
||||
}
|
||||
},
|
||||
|
||||
isRunningService: Ember.computed('model.serviceName', 'model.app.state', function () {
|
||||
return this.model.serviceName && this.model.app.get('state') === 'RUNNING';
|
||||
}),
|
||||
|
||||
|
||||
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
|
||||
var breadcrumbs = [{
|
||||
text: "Home",
|
||||
|
@ -58,5 +117,13 @@ export default Ember.Controller.extend({
|
|||
breadcrumbs.pushObjects(tailCrumbs);
|
||||
}
|
||||
this.set('breadcrumbs', breadcrumbs);
|
||||
}
|
||||
},
|
||||
|
||||
amHostHttpAddressFormatted: Ember.computed('model.app.amHostHttpAddress', function () {
|
||||
var amHostAddress = this.get('model.app.amHostHttpAddress');
|
||||
if (amHostAddress && amHostAddress.indexOf('://') < 0) {
|
||||
amHostAddress = 'http://' + amHostAddress;
|
||||
}
|
||||
return amHostAddress;
|
||||
})
|
||||
});
|
||||
|
|
|
@ -32,7 +32,7 @@ function createColumn() {
|
|||
minWidth: "300px",
|
||||
getCellContent: function (row) {
|
||||
return {
|
||||
routeName: 'yarn-app.info',
|
||||
routeName: 'yarn-app.attempts',
|
||||
id: row.get('appId'),
|
||||
displayText: row.get('appId')
|
||||
};
|
||||
|
|
|
@ -33,7 +33,7 @@ export default DS.Model.extend({
|
|||
amContainerLogs: DS.attr('string'),
|
||||
amHostHttpAddress: DS.attr('string'),
|
||||
logAggregationStatus: DS.attr('string'),
|
||||
unmanagedApplication: DS.attr('string'),
|
||||
unmanagedApplication: DS.attr('boolean'),
|
||||
amNodeLabelExpression: DS.attr('string'),
|
||||
applicationTags: DS.attr('string'),
|
||||
applicationType: DS.attr('string'),
|
||||
|
@ -65,6 +65,10 @@ export default DS.Model.extend({
|
|||
return this.get("finishedTime");
|
||||
}.property("finishedTime"),
|
||||
|
||||
hasFinishedTime: function() {
|
||||
return this.get("finishedTime") >= this.get("startTime");
|
||||
}.property("hasFinishedTime"),
|
||||
|
||||
formattedElapsedTime: function() {
|
||||
return Converter.msToElapsedTimeUnit(this.get('elapsedTime'));
|
||||
}.property('elapsedTime'),
|
||||
|
|
|
@ -54,12 +54,12 @@ Router.map(function() {
|
|||
|
||||
this.route('yarn-deploy-service');
|
||||
this.route('cluster-overview');
|
||||
this.route('yarn-app', function() {
|
||||
this.route('info', {path: '/:app_id/info'});
|
||||
this.route('attempts', {path: '/:app_id/attempts'});
|
||||
this.route('components', {path: '/:app_id/components'});
|
||||
this.route('charts', {path: '/:app_id/charts'});
|
||||
this.route('configs', {path: '/:app_id/configs'});
|
||||
this.route('yarn-app', { path: '/yarn-app/:app_id' }, function() {
|
||||
this.route('info');
|
||||
this.route('attempts');
|
||||
this.route('components');
|
||||
this.route('charts');
|
||||
this.route('configs');
|
||||
});
|
||||
this.route('yarn-component-instances', function() {
|
||||
this.route('info', {path: '/:component_name/info'});
|
||||
|
|
|
@ -16,9 +16,30 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import Ember from 'ember';
|
||||
import AbstractRoute from './abstract';
|
||||
import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
|
||||
|
||||
export default AbstractRoute.extend({
|
||||
export default AbstractRoute.extend(AppAttemptMixin, {
|
||||
model(param, transition) {
|
||||
const {service} = transition.queryParams;
|
||||
transition.send('updateBreadcrumbs', param.app_id, service);
|
||||
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: service,
|
||||
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store),
|
||||
|
||||
quicklinks: this.store.queryRecord('yarn-service-info', { appId: param.app_id }).then(function (info) {
|
||||
if (info && info.get('quicklinks')) {
|
||||
return info.get('quicklinks');
|
||||
}
|
||||
return [];
|
||||
}, function () {
|
||||
return [];
|
||||
})
|
||||
});
|
||||
},
|
||||
actions: {
|
||||
updateBreadcrumbs(appId, serviceName, tailCrumbs) {
|
||||
var controller = this.controllerFor('yarn-app');
|
||||
|
|
|
@ -22,14 +22,21 @@ import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
|
|||
|
||||
export default AbstractRoute.extend(AppAttemptMixin, {
|
||||
model(param, transition) {
|
||||
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: 'Attempts'}]);
|
||||
const {app_id} = this.paramsFor('yarn-app');
|
||||
const {service} = param;
|
||||
|
||||
transition.send('updateBreadcrumbs', app_id, service, [{text: 'Attempts'}]);
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: param.service,
|
||||
attempts: this.fetchAttemptListFromRMorATS(param.app_id, this.store)
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
attempts: this.fetchAttemptListFromRMorATS(app_id, this.store)
|
||||
});
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-app-attempt');
|
||||
this.store.unloadAll('yarn-timeline-appattempt');
|
||||
|
|
|
@ -21,15 +21,17 @@ import AbstractRoute from '../abstract';
|
|||
|
||||
export default AbstractRoute.extend({
|
||||
model(param, transition) {
|
||||
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: "Charts"}]);
|
||||
const { app_id } = this.paramsFor('yarn-app');
|
||||
const { service } = param;
|
||||
transition.send('updateBreadcrumbs', app_id, service, [{text: "Charts"}]);
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: param.service,
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
|
||||
app: this.store.find('yarn-app', param.app_id),
|
||||
app: this.store.find('yarn-app', app_id),
|
||||
|
||||
rmContainers: this.store.find('yarn-app', param.app_id).then(function() {
|
||||
return this.store.query('yarn-app-attempt', {appId: param.app_id}).then(function (attempts) {
|
||||
rmContainers: this.store.find('yarn-app', app_id).then(function() {
|
||||
return this.store.query('yarn-app-attempt', {appId: app_id}).then(function (attempts) {
|
||||
if (attempts && attempts.get('firstObject')) {
|
||||
var appAttemptId = attempts.get('firstObject').get('appAttemptId');
|
||||
return this.store.query('yarn-container', {
|
||||
|
@ -44,6 +46,10 @@ export default AbstractRoute.extend({
|
|||
});
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-app');
|
||||
this.store.unloadAll('yarn-app-attempt');
|
||||
|
|
|
@ -21,14 +21,16 @@ import AbstractRoute from '../abstract';
|
|||
|
||||
export default AbstractRoute.extend({
|
||||
model(param, transition) {
|
||||
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: 'Components'}]);
|
||||
const { app_id } = this.paramsFor('yarn-app');
|
||||
const { service } = param;
|
||||
transition.send('updateBreadcrumbs', app_id, service, [{text: 'Components'}]);
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: param.service,
|
||||
components: this.store.query('yarn-service-component', {appId: param.app_id, type: 'COMPONENT'}).catch(function() {
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
components: this.store.query('yarn-service-component', {appId: app_id, type: 'COMPONENT'}).catch(function() {
|
||||
return [];
|
||||
}),
|
||||
instances: this.store.query('yarn-component-instance', {appId: param.app_id}).catch(function() {
|
||||
instances: this.store.query('yarn-component-instance', {appId: app_id}).catch(function() {
|
||||
return [];
|
||||
})
|
||||
});
|
||||
|
@ -42,6 +44,10 @@ export default AbstractRoute.extend({
|
|||
});
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-service-component');
|
||||
this.store.unloadAll('yarn-component-instance');
|
||||
|
|
|
@ -21,12 +21,14 @@ import AbstractRoute from '../abstract';
|
|||
|
||||
export default AbstractRoute.extend({
|
||||
model(param, transition) {
|
||||
transition.send('updateBreadcrumbs', param.app_id, param.service, [{text: "Configurations & Metrics"}]);
|
||||
const { app_id } = this.paramsFor('yarn-app');
|
||||
const { service } = param;
|
||||
transition.send('updateBreadcrumbs', app_id, service, [{text: "Configurations & Metrics"}]);
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: param.service,
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
|
||||
configs: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
|
||||
configs: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
|
||||
if (info && info.get('configs')) {
|
||||
return info.get('configs');
|
||||
}
|
||||
|
@ -35,7 +37,7 @@ export default AbstractRoute.extend({
|
|||
return [];
|
||||
}),
|
||||
|
||||
metrics: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
|
||||
metrics: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
|
||||
if (info && info.get('metrics')) {
|
||||
return info.get('metrics');
|
||||
}
|
||||
|
@ -46,6 +48,10 @@ export default AbstractRoute.extend({
|
|||
});
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-service-info');
|
||||
}
|
||||
|
|
|
@ -22,13 +22,16 @@ import AppAttemptMixin from 'yarn-ui/mixins/app-attempt';
|
|||
|
||||
export default AbstractRoute.extend(AppAttemptMixin, {
|
||||
model(param, transition) {
|
||||
transition.send('updateBreadcrumbs', param.app_id, param.service);
|
||||
return Ember.RSVP.hash({
|
||||
appId: param.app_id,
|
||||
serviceName: param.service,
|
||||
app: this.fetchAppInfoFromRMorATS(param.app_id, this.store),
|
||||
const { app_id } = this.paramsFor('yarn-app');
|
||||
const { service } = param;
|
||||
transition.send('updateBreadcrumbs', app_id, service);
|
||||
|
||||
quicklinks: this.store.queryRecord('yarn-service-info', {appId: param.app_id}).then(function(info) {
|
||||
return Ember.RSVP.hash({
|
||||
appId: app_id,
|
||||
serviceName: service,
|
||||
app: this.fetchAppInfoFromRMorATS(app_id, this.store),
|
||||
|
||||
quicklinks: this.store.queryRecord('yarn-service-info', {appId: app_id}).then(function(info) {
|
||||
if (info && info.get('quicklinks')) {
|
||||
return info.get('quicklinks');
|
||||
}
|
||||
|
@ -39,6 +42,10 @@ export default AbstractRoute.extend(AppAttemptMixin, {
|
|||
});
|
||||
},
|
||||
|
||||
refresh() {
|
||||
window.location.reload();
|
||||
},
|
||||
|
||||
unloadAll() {
|
||||
this.store.unloadAll('yarn-app');
|
||||
this.store.unloadAll('yarn-app-timeline');
|
||||
|
|
|
@ -52,7 +52,7 @@ export default DS.JSONAPISerializer.extend({
|
|||
amContainerLogs: payload.amContainerLogs,
|
||||
amHostHttpAddress: payload.amHostHttpAddress,
|
||||
logAggregationStatus: payload.logAggregationStatus,
|
||||
unmanagedApplication: payload.unmanagedApplication || 'N/A',
|
||||
unmanagedApplication: payload.unmanagedApplication,
|
||||
amNodeLabelExpression: payload.amNodeLabelExpression,
|
||||
priority: (payload.priority !== undefined)? payload.priority : 'N/A',
|
||||
allocatedMB: payload.allocatedMB,
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
@import 'variables.scss';
|
||||
@import 'layout.scss';
|
||||
@import 'yarn-app.scss';
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
|
@ -497,6 +499,9 @@ div.attempt-info-panel table > tbody > tr > td:last-of-type {
|
|||
.align-center {
|
||||
text-align: center !important;
|
||||
}
|
||||
.align-right {
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.bold-text {
|
||||
font-weight: bold !important;
|
||||
|
@ -717,7 +722,26 @@ div.service-action-mask img {
|
|||
line-height: 2em;
|
||||
}
|
||||
|
||||
.yarn-app-body > div:not(:first-child) {
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.em-table .table-column .table-header-cell {
|
||||
background-color: $yarn-header-bg;
|
||||
border-bottom: 1px solid $yarn-border-color;
|
||||
}
|
||||
|
||||
.muted-text {
|
||||
color: $yarn-muted-text;
|
||||
}
|
||||
|
||||
.glyphicon-gray {
|
||||
color: $yarn-gray-icon;
|
||||
}
|
||||
|
||||
.btn.btn-unstyled {
|
||||
padding: 5px;
|
||||
background: none;
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
}
|
|
@ -21,6 +21,8 @@ $color-ghost-white: #f1f2f8;
|
|||
$color-white: #fff;
|
||||
|
||||
$color-gray-20: #333;
|
||||
$color-gray-40: #666666;
|
||||
$color-gray-60: #999999;
|
||||
$color-gray-97: #f7f7f7;
|
||||
$color-light-gray: #d5d5d5;
|
||||
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
/** Pushes the flex element to the right corner **/
|
||||
.flex-right {
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.offset-1 {
|
||||
margin-left: 5px
|
||||
}
|
||||
|
||||
.offset-2 {
|
||||
margin-left: 10px
|
||||
}
|
||||
|
||||
.tail-1 {
|
||||
margin-right: 5px
|
||||
}
|
||||
|
||||
.tail-2 {
|
||||
margin-right: 10px
|
||||
}
|
|
@ -36,5 +36,9 @@ $yarn-info-bg: $color-blue-primary;
|
|||
$yarn-warn-border: $color-yellow-secondary;
|
||||
$yarn-warn-bg: $color-yellow-primary;
|
||||
|
||||
$yarn-gray-icon: $color-gray-40;
|
||||
|
||||
$yarn-muted-text: $color-gray-60;
|
||||
|
||||
|
||||
//shadows
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.yarn-app-header {
|
||||
padding: 20px;
|
||||
line-height: 2em;
|
||||
|
||||
h3 {
|
||||
margin: 0px;
|
||||
}
|
||||
|
||||
i.glyphicon {
|
||||
vertical-align: text-top;
|
||||
margin-right: 3px;
|
||||
}
|
||||
|
||||
.yarn-app-final-status .label {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
{{#if attemptModel}}
|
||||
|
|
|
@ -18,46 +18,131 @@
|
|||
|
||||
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
|
||||
|
||||
<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">
|
||||
{{#if serviceName}}
|
||||
Service
|
||||
{{else}}
|
||||
Application
|
||||
{{/if}}
|
||||
<div class="panel-group">
|
||||
<div class="panel panel-default">
|
||||
<div class="yarn-app-header">
|
||||
<div class="flex">
|
||||
<div>
|
||||
<div class="flex">
|
||||
<div>
|
||||
<h3 class="yarn-app-name">
|
||||
{{#if model.app.unmanagedApplication}}
|
||||
<span title="This is an unmanaged application" class="yarn-tooltip">
|
||||
<i class="glyphicon glyphicon-exclamation-sign glyphicon-gray" />
|
||||
</span>
|
||||
{{/if}}
|
||||
{{model.app.appName}}
|
||||
</h3>
|
||||
</div>
|
||||
{{#if model.app.finalStatus}}
|
||||
<div title="Final status" class="yarn-tooltip yarn-app-final-status offset-1">
|
||||
<span class={{model.app.finalStatusStyle}}>
|
||||
{{model.app.finalStatus}}
|
||||
</span>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div title="Application id" class="muted-text">{{model.app.id}}</div>
|
||||
{{em-table-simple-status-cell content=model.app.state}}
|
||||
<div class="flex">
|
||||
<div class="tail-2">
|
||||
<i class="glyphicon glyphicon-user glyphicon-gray" /> {{model.app.user}}
|
||||
</div>
|
||||
{{#if model.app.hasFinishedTime}}
|
||||
<div title="Started at {{model.app.startTime}}. Ran for {{model.app.formattedElapsedTime}}" class="yarn-tooltip">
|
||||
<i class="glyphicon glyphicon-time glyphicon-gray" />
|
||||
Finished at {{model.app.validatedFinishedTs}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div title="Running for {{model.app.formattedElapsedTime}}" class="yarn-tooltip">
|
||||
<i class="glyphicon glyphicon-time glyphicon-gray" />
|
||||
Started at {{model.app.startTime}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</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-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
|
||||
{{#link-to 'yarn-app.info' appId (query-params service=serviceName)}}Information{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.attempts' tagName="li" class=(if (eq target.currentPath 'yarn-app.attempts') "active")}}
|
||||
{{#link-to 'yarn-app.attempts' appId (query-params service=serviceName)}}Attempts List{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.charts' tagName="li" class=(if (eq target.currentPath 'yarn-app.charts') "active")}}
|
||||
{{#link-to 'yarn-app.charts' appId (query-params service=serviceName)}}Resource Usage{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#if serviceName}}
|
||||
{{#link-to 'yarn-app.components' tagName="li" class=(if (eq target.currentPath 'yarn-app.components') "active")}}
|
||||
{{#link-to 'yarn-app.components' appId (query-params service=serviceName)}}Components{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.configs' tagName="li" class=(if (eq target.currentPath 'yarn-app.configs') "active")}}
|
||||
{{#link-to 'yarn-app.configs' appId (query-params service=serviceName)}}Configurations & Metrics{{/link-to}}
|
||||
{{/link-to}}
|
||||
|
||||
<div class="flex-right">
|
||||
<div class="links">
|
||||
<a href="{{model.app.amContainerLogs}}" target="_blank">Master Container Log</a> |
|
||||
<a href="{{amHostHttpAddressFormatted}}" target="_blank">Master Node</a> |
|
||||
{{#if isRunningService}}
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-unstyled dropdown-toggle" title="Settings" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="glyphicon glyphicon-cog" />
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
<li>
|
||||
<a href="#" {{action "showStopServiceConfirm"}} target="_blank"><i class="glyphicon glyphicon-stop" /> Stop Service</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="#" target="_blank" {{action "showDeleteServiceConfirm"}}><i class="glyphicon glyphicon-trash" /> Delete Service </a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#if model.serviceName}}
|
||||
{{#if model.quicklinks}}
|
||||
<div class="btn-group">
|
||||
<button type="button" class="btn btn-unstyled dropdown-toggle" title="Quick links" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<i class="glyphicon glyphicon-option-vertical" />
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-right">
|
||||
{{#each model.quicklinks as |link|}}
|
||||
<li><a href="{{link.value}}" target="_blank">{{link.name}}</a></li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
</ul>
|
||||
</ul>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div>
|
||||
<span title="Queue" class="yarn-tooltip"><i class="glyphicon glyphicon-tasks glyphicon-gray" />{{model.app.queue}}</span>
|
||||
</div>
|
||||
<div>Priority {{model.app.priority}}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-10 container-fluid">
|
||||
<div class="panel-heading">
|
||||
<div class="clearfix">
|
||||
<ul class="nav nav-pills">
|
||||
<ul class="nav nav-pills collapse in">
|
||||
{{#link-to 'yarn-app.attempts' tagName="li" class=(if (eq target.currentPath 'yarn-app.attempts') "active")}}
|
||||
{{#link-to 'yarn-app.attempts' appId (query-params service=model.serviceName)}}Attempts List{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.charts' tagName="li" class=(if (eq target.currentPath 'yarn-app.charts') "active")}}
|
||||
{{#link-to 'yarn-app.charts' appId (query-params service=model.serviceName)}}Resource Usage{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#if model.serviceName}}
|
||||
{{#link-to 'yarn-app.components' tagName="li" class=(if (eq target.currentPath 'yarn-app.components') "active")}}
|
||||
{{#link-to 'yarn-app.components' appId (query-params service=model.serviceName)}}Components{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{#link-to 'yarn-app.configs' tagName="li" class=(if (eq target.currentPath 'yarn-app.configs') "active")}}
|
||||
{{#link-to 'yarn-app.configs' appId (query-params service=model.serviceName)}}Configurations & Metrics{{/link-to}}
|
||||
{{/link-to}}
|
||||
{{/if}}
|
||||
{{#link-to 'yarn-app.info' tagName="li" class=(if (eq target.currentPath 'yarn-app.info') "active")}}
|
||||
{{#link-to 'yarn-app.info' appId (query-params service=model.serviceName)}}Diagnostics{{/link-to}}
|
||||
{{/link-to}}
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel-body yarn-app-body">
|
||||
{{outlet}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{confirm-dialog
|
||||
dialogId="stopServiceConfirmDialog"
|
||||
message=(concat 'Are you sure you want to stop service "' model.serviceName '" ?')
|
||||
action="stopService"
|
||||
}}
|
||||
|
||||
{{confirm-dialog
|
||||
dialogId="deleteServiceConfirmDialog"
|
||||
message=(concat 'Are you sure you want to delete service "' model.serviceName '" ?')
|
||||
action="deleteService"
|
||||
}}
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="row">
|
||||
<div>
|
||||
{{timeline-view
|
||||
parent-id="attempt-timeline-div"
|
||||
my-id="timeline-view"
|
||||
|
|
|
@ -16,28 +16,26 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 container-fluid">
|
||||
{{#if isRunningApp}}
|
||||
<div class="row" id="stackd-bar-chart-mem">
|
||||
{{per-app-memusage-by-nodes-stacked-barchart
|
||||
nodes=model.nodes
|
||||
rmContainers=model.rmContainers
|
||||
parentId="stackd-bar-chart-mem"
|
||||
title=(concat 'Memory usage by nodes for: [' model.appId ']')}}
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row" id="stackd-bar-chart-ncontainer">
|
||||
{{per-app-ncontainers-by-nodes-stacked-barchart
|
||||
nodes=model.nodes
|
||||
rmContainers=model.rmContainers
|
||||
parentId="stackd-bar-chart-ncontainer"
|
||||
title=(concat 'Running #Containers by nodes for: [' model.appId ']')}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel panel-default">
|
||||
<h4 class="text-center">No resource usage data is available for this application!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{{#if isRunningApp}}
|
||||
<div class="row" id="stackd-bar-chart-mem">
|
||||
{{per-app-memusage-by-nodes-stacked-barchart
|
||||
nodes=model.nodes
|
||||
rmContainers=model.rmContainers
|
||||
parentId="stackd-bar-chart-mem"
|
||||
title=(concat 'Memory usage by nodes for: [' model.appId ']')}}
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row" id="stackd-bar-chart-ncontainer">
|
||||
{{per-app-ncontainers-by-nodes-stacked-barchart
|
||||
nodes=model.nodes
|
||||
rmContainers=model.rmContainers
|
||||
parentId="stackd-bar-chart-ncontainer"
|
||||
title=(concat 'Running #Containers by nodes for: [' model.appId ']')}}
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel panel-default">
|
||||
<h4 class="text-center">No resource usage data is available for this application!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
|
@ -16,8 +16,6 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{em-table columns=tableColumns rows=model.components}}
|
||||
</div>
|
||||
<div class="col-md-12 yarn-applications-container">
|
||||
{{em-table columns=tableColumns rows=model.components}}
|
||||
</div>
|
||||
|
|
|
@ -20,38 +20,36 @@
|
|||
{{metrics-table metrics=model.metrics type="Service"}}
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
{{#if model.configs}}
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-title">Service Configurations</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<table class="table table-hover table-custom-bordered table-custom-stripped table-radius-none table-border-none">
|
||||
<thead>
|
||||
{{#if model.configs}}
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<div class="panel-title">Service Configurations</div>
|
||||
</div>
|
||||
<div class="">
|
||||
<table class="table table-hover table-custom-bordered table-custom-stripped table-radius-none table-border-none">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.configs as |config|}}
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>Value</th>
|
||||
<td>{{config.name}}</td>
|
||||
<td>{{config.value}}</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.configs as |config|}}
|
||||
<tr>
|
||||
<td>{{config.name}}</td>
|
||||
<td>{{config.value}}</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<h4 class="text-center">No service configurations available!</h4>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<h4 class="text-center">No service configurations available!</h4>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
|
|
@ -16,19 +16,15 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
{{app-timeout-bar app=model.app}}
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
{{app-timeout-bar app=model.app}}
|
||||
</div>
|
||||
|
||||
{{#if actionResponse}}
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-dismissible {{if (eq actionResponse.type 'error') 'alert-danger' 'alert-success'}}" role="alert">
|
||||
<button class="close" data-dismiss="alert" aria-label="Close" {{action "resetActionResponse"}}><span aria-hidden="true">×</span></button>
|
||||
<strong>{{actionResponse.msg}}</strong>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="alert alert-dismissible {{if (eq actionResponse.type 'error') 'alert-danger' 'alert-success'}}" role="alert">
|
||||
<button class="close" data-dismiss="alert" aria-label="Close" {{action "resetActionResponse"}}><span aria-hidden="true">×</span></button>
|
||||
<strong>{{actionResponse.msg}}</strong>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
@ -39,220 +35,95 @@
|
|||
</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Basic Info
|
||||
{{#if isRunningService}}
|
||||
<div class="pull-right" style="display: inline-block; margin: -4px -10px 0 0;">
|
||||
<button class="btn btn-sm btn-danger" disabled="{{if isLoading 'disabled'}}" {{action "showStopServiceConfirm"}}> Stop </button>
|
||||
<button class="btn btn-sm btn-danger" disabled="{{if isLoading 'disabled'}}" {{action "showDeleteServiceConfirm"}}> Delete </button>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#if model.app.diagnostics}}
|
||||
<div class="col-md-12">
|
||||
{{#if model.app.isFailed}}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
Diagnostics
|
||||
</div>
|
||||
<div class="panel-body">{{model.app.diagnostics}}</div>
|
||||
</div>
|
||||
<div class="x-scroll">
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Application ID</th>
|
||||
<th>Name</th>
|
||||
<th>User</th>
|
||||
<th>Queue</th>
|
||||
<th>State</th>
|
||||
<th>Final Status</th>
|
||||
<th>Start Time</th>
|
||||
<th>Elapsed Time</th>
|
||||
<th>Finished Time</th>
|
||||
<th>Priority</th>
|
||||
{{#unless model.serviceName}}
|
||||
<th>Progress</th>
|
||||
<th>Is Unmanaged AM</th>
|
||||
{{/unless}}
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{model.app.id}}</td>
|
||||
<td>{{model.app.appName}}</td>
|
||||
<td>{{model.app.user}}</td>
|
||||
<td>{{model.app.queue}}</td>
|
||||
<td>{{model.app.state}}</td>
|
||||
<td>
|
||||
<span class={{model.app.finalStatusStyle}}>
|
||||
{{model.app.finalStatus}}
|
||||
</span>
|
||||
</td>
|
||||
<td>{{model.app.startTime}}</td>
|
||||
<td>{{model.app.formattedElapsedTime}}</td>
|
||||
<td>{{model.app.validatedFinishedTs}}</td>
|
||||
<td>{{model.app.priority}}</td>
|
||||
{{#unless model.serviceName}}
|
||||
<td>
|
||||
<div class="progress" style="margin-bottom: 0;">
|
||||
<div class="progress-bar" role="progressbar"
|
||||
aria-valuenow="60" aria-valuemin="0"
|
||||
aria-valuemax="100"
|
||||
style={{model.app.progressStyle}}>
|
||||
{{model.app.progress}}%
|
||||
</div>
|
||||
</div>
|
||||
</td>
|
||||
<td>{{model.app.unmanagedApplication}}</td>
|
||||
{{/unless}}
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
{{else}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Diagnostics
|
||||
</div>
|
||||
<div class="panel-body">{{model.app.diagnostics}}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
{{#if model.app.diagnostics}}
|
||||
<div class="col-md-12 container-fluid">
|
||||
{{#if model.app.isFailed}}
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
Diagnostics
|
||||
</div>
|
||||
<div class="panel-body">{{model.app.diagnostics}}</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
Diagnostics
|
||||
</div>
|
||||
<div class="panel-body">{{model.app.diagnostics}}</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{#unless model.serviceName}}
|
||||
<div class="row">
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Outstanding Resource Requests</div>
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Outstanding Resource Requests</div>
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Scheduler Key</th>
|
||||
<th>Resource Name</th>
|
||||
<th>Capability</th>
|
||||
<th># Containers</th>
|
||||
<th>Relax Locality</th>
|
||||
<th>Node Label Expression</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.app.resourceRequests as |request|}}
|
||||
<tr>
|
||||
<th>Scheduler Key</th>
|
||||
<th>Resource Name</th>
|
||||
<th>Capability</th>
|
||||
<th># Containers</th>
|
||||
<th>Relax Locality</th>
|
||||
<th>Node Label Expression</th>
|
||||
<td>{{request.priority}}</td>
|
||||
<td>{{request.resourceName}}</td>
|
||||
<td><Memory:{{request.capability.memory}};vCores:{{request.capability.virtualCores}}></td>
|
||||
<td>{{request.numContainers}}</td>
|
||||
<td>{{request.relaxLocality}}</td>
|
||||
<td>
|
||||
{{#if request.nodeLabelExpression}}
|
||||
{{request.nodeLabelExpression}}
|
||||
{{else}}
|
||||
N/A
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{{#each model.app.resourceRequests as |request|}}
|
||||
<tr>
|
||||
<td>{{request.priority}}</td>
|
||||
<td>{{request.resourceName}}</td>
|
||||
<td><Memory:{{request.capability.memory}};vCores:{{request.capability.virtualCores}}></td>
|
||||
<td>{{request.numContainers}}</td>
|
||||
<td>{{request.relaxLocality}}</td>
|
||||
<td>
|
||||
{{#if request.nodeLabelExpression}}
|
||||
{{request.nodeLabelExpression}}
|
||||
{{else}}
|
||||
N/A
|
||||
{{/if}}
|
||||
</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<div class="panel-body">No data available!</div>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="panel-body">No data available!</div>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{/unless}}
|
||||
<div class="row">
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Scheduling Info</div>
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Allocated Resource</th>
|
||||
<th>Running Containers</th>
|
||||
<th>Preempted Resource</th>
|
||||
<th>Num Non-AM container preempted</th>
|
||||
<th>Num AM container preempted</th>
|
||||
<th>Aggregated Resource Usage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{model.app.allocatedResource}}</td>
|
||||
<td>{{model.app.runningContainersNumber}}</td>
|
||||
<td>{{model.app.preemptedResource}}</td>
|
||||
<td>{{model.app.numAMContainerPreempted}}</td>
|
||||
<td>{{model.app.numAMContainerPreempted}}</td>
|
||||
<td>{{model.app.aggregatedResourceUsage}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-12">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Scheduling Info</div>
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Allocated Resource</th>
|
||||
<th>Running Containers</th>
|
||||
<th>Preempted Resource</th>
|
||||
<th>Num Non-AM container preempted</th>
|
||||
<th>Num AM container preempted</th>
|
||||
<th>Aggregated Resource Usage</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>{{model.app.allocatedResource}}</td>
|
||||
<td>{{model.app.runningContainersNumber}}</td>
|
||||
<td>{{model.app.preemptedResource}}</td>
|
||||
<td>{{model.app.numAMContainerPreempted}}</td>
|
||||
<td>{{model.app.numAMContainerPreempted}}</td>
|
||||
<td>{{model.app.aggregatedResourceUsage}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Application Master Info</div>
|
||||
<table class="display table table-striped table-bordered"
|
||||
cellspacing="0" width="100%">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Master Container Log</th>
|
||||
<th>Master Node</th>
|
||||
<th>Master Node Label Expression</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><a href="{{model.app.amContainerLogs}}" target="_blank">Link</a></td>
|
||||
<td><a href="{{amHostHttpAddressFormatted}}" target="_blank">Link</a></td>
|
||||
<td>{{model.app.amNodeLabelExpression}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{{#if model.serviceName}}
|
||||
<div class="col-md-6 container-fluid">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Quick Links</div>
|
||||
<table class="display table table-striped table-bordered">
|
||||
<tbody>
|
||||
{{#each model.quicklinks as |link|}}
|
||||
<tr>
|
||||
<td>{{link.name}}</td>
|
||||
<td><a href="{{link.value}}" target="_blank">{{link.value}}</a></td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr class="align-center">
|
||||
<td colspan="2">No quicklinks available!</td>
|
||||
</tr>
|
||||
{{/each}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{confirm-dialog
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
* limitations under the License.
|
||||
}}
|
||||
|
||||
<div class="col-md-12 container-fluid">
|
||||
<div class="col-md-12">
|
||||
<div class="loading-mask">
|
||||
<img src="assets/images/spinner.gif" alt="Loading...">
|
||||
</div>
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
--}}
|
||||
|
||||
{{breadcrumb-bar breadcrumbs=breadcrumbs}}
|
||||
|
||||
<a class="btn btn-primary pull-right" href="#/yarn-deploy-service">New Service</a>
|
||||
<div class="col-md-12 container-fluid yarn-applications-container">
|
||||
{{#if model.apps}}
|
||||
{{em-table columns=serviceColumns rows=model.apps definition=tableDefinition}}
|
||||
|
|
Loading…
Reference in New Issue