mirror of https://github.com/rancher/ui.git
Cluster stats, things
This commit is contained in:
parent
3fa04f29e6
commit
fe7ccc4a18
|
|
@ -2,15 +2,16 @@ import { computed } from '@ember/object';
|
|||
import { equal } from '@ember/object/computed';
|
||||
import { inject as service } from '@ember/service';
|
||||
import Resource from 'ember-api-store/models/resource';
|
||||
import PolledResource from 'ui/mixins/cattle-polled-resource';
|
||||
import { hasMany } from 'ember-api-store/utils/denormalize';
|
||||
import ResourceUsage from 'shared/mixins/resource-usage';
|
||||
|
||||
var Cluster = Resource.extend(PolledResource, {
|
||||
var Cluster = Resource.extend(ResourceUsage, {
|
||||
scope: service(),
|
||||
router: service(),
|
||||
|
||||
namespaces: hasMany('id', 'namespace', 'clusterId'),
|
||||
projects: hasMany('id', 'project', 'clusterId'),
|
||||
machines: hasMany('id', 'machine', 'clusterId'),
|
||||
clusterRoleTemplateBindings: hasMany('id', 'clusterRoleTemplateBinding', 'clusterId'),
|
||||
|
||||
canAddNode: true, // @TODO-2.0
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
import { computed, get } from '@ember/object';
|
||||
import { alias } from '@ember/object/computed';
|
||||
import Resource from 'ember-api-store/models/resource';
|
||||
import { formatPercent, download } from 'shared/utils/util';
|
||||
import { formatSi, parseSi, exponentNeeded } from 'shared/utils/parse-unit';
|
||||
import { download } from 'shared/utils/util';
|
||||
import C from 'ui/utils/constants';
|
||||
import StateCounts from 'ui/mixins/state-counts';
|
||||
import { inject as service } from "@ember/service";
|
||||
import { reference } from 'ember-api-store/utils/denormalize';
|
||||
import ResourceUsage from 'shared/mixins/resource-usage';
|
||||
|
||||
|
||||
var Machine = Resource.extend(StateCounts,{
|
||||
var Machine = Resource.extend(StateCounts, ResourceUsage, {
|
||||
type: 'machine',
|
||||
modalService: service('modal'),
|
||||
settings: service(),
|
||||
|
|
@ -34,7 +34,7 @@ var Machine = Resource.extend(StateCounts,{
|
|||
},
|
||||
|
||||
promptEvacuate: function() {
|
||||
this.get('modalService').toggleModal('modal-host-evacuate', {
|
||||
get(this,'modalService').toggleModal('modal-host-evacuate', {
|
||||
model: [this]
|
||||
});
|
||||
},
|
||||
|
|
@ -44,15 +44,15 @@ var Machine = Resource.extend(StateCounts,{
|
|||
},
|
||||
|
||||
newContainer: function() {
|
||||
this.get('router').transitionTo('containers.run', {queryParams: {hostId: this.get('model.id')}});
|
||||
get(this,'router').transitionTo('containers.run', {queryParams: {hostId: get(this,'model.id')}});
|
||||
},
|
||||
|
||||
clone: function() {
|
||||
this.get('router').transitionTo('hosts.new', {queryParams: {hostId: this.get('id'), driver: this.get('driver')}});
|
||||
get(this,'router').transitionTo('hosts.new', {queryParams: {hostId: get(this,'id'), driver: get(this,'driver')}});
|
||||
},
|
||||
|
||||
edit: function() {
|
||||
this.get('modalService').toggleModal('modal-edit-host', this);
|
||||
get(this,'modalService').toggleModal('modal-edit-host', this);
|
||||
},
|
||||
|
||||
machineConfig: function() {
|
||||
|
|
@ -65,18 +65,18 @@ var Machine = Resource.extend(StateCounts,{
|
|||
},
|
||||
|
||||
availableActions: function() {
|
||||
let a = this.get('actionLinks');
|
||||
let l = this.get('links');
|
||||
let a = get(this,'actionLinks');
|
||||
let l = get(this,'links');
|
||||
|
||||
let out = [
|
||||
{ label: 'action.machineConfig', icon: 'icon icon-download', action: 'machineConfig', enabled: !!l.config},
|
||||
{ divider: true },
|
||||
{ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: !!l.update },
|
||||
{ divider: true },
|
||||
{ label: 'action.activate', icon: 'icon icon-play', action: 'activate', enabled: !!a.activate, bulkable: true},
|
||||
{ label: 'action.deactivate', icon: 'icon icon-pause', action: 'deactivate', enabled: !!a.deactivate, bulkable: true},
|
||||
{ label: 'action.evacuate', icon: 'icon icon-snapshot', action: 'promptEvacuate',enabled: !!a.evacuate, altAction: 'evacuate', bulkable: true},
|
||||
{ divider: true },
|
||||
// { label: 'action.activate', icon: 'icon icon-play', action: 'activate', enabled: !!a.activate, bulkable: true},
|
||||
// { label: 'action.deactivate', icon: 'icon icon-pause', action: 'deactivate', enabled: !!a.deactivate, bulkable: true},
|
||||
// { label: 'action.evacuate', icon: 'icon icon-snapshot', action: 'promptEvacuate',enabled: !!a.evacuate, altAction: 'evacuate', bulkable: true},
|
||||
// { divider: true },
|
||||
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove, altAction: 'delete', bulkable: true},
|
||||
{ divider: true },
|
||||
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true},
|
||||
|
|
@ -88,12 +88,12 @@ var Machine = Resource.extend(StateCounts,{
|
|||
displayIp: alias('ipAddress'),
|
||||
|
||||
displayName: computed('name','nodeName','id', function() {
|
||||
let name = this.get('name');
|
||||
let name = get(this,'name');
|
||||
if ( name ) {
|
||||
return name;
|
||||
}
|
||||
|
||||
name = this.get('nodeName');
|
||||
name = get(this,'nodeName');
|
||||
if ( name ) {
|
||||
if ( name.match(/[a-z]/i) ) {
|
||||
name = name.replace(/\..*$/,'');
|
||||
|
|
@ -102,83 +102,23 @@ var Machine = Resource.extend(StateCounts,{
|
|||
return name;
|
||||
}
|
||||
|
||||
name = this.get('requestedHostname');
|
||||
name = get(this,'requestedHostname');
|
||||
if ( name ) {
|
||||
return name;
|
||||
}
|
||||
|
||||
return '('+this.get('id')+')';
|
||||
}),
|
||||
|
||||
cpuUsage: computed('requested.cpu','allocatable.cpu', function() {
|
||||
const used = parseSi(get(this,'requested.cpu'));
|
||||
const total = parseSi(get(this,'allocatable.cpu'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1000, '', '', 0, minExp).replace(/\s.*$/,'');
|
||||
const totalStr = formatSi(total, 1000, '', '', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
cpuPercent: computed('requested.cpu','allocatable.cpu', function() {
|
||||
const used = parseSi(get(this,'requested.cpu'));
|
||||
const total = parseSi(get(this,'allocatable.cpu'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
}),
|
||||
|
||||
memoryUsage: computed('requested.memory','allocatable.memory', function() {
|
||||
const used = parseSi(get(this,'requested.memory'));
|
||||
const total = parseSi(get(this,'allocatable.memory'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1024, '', '', 0, minExp).replace(/\s.*/,'');
|
||||
const totalStr = formatSi(total, 1024, 'iB', 'B', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
memoryPercent: computed('requested.memory','allocatable.memory', function() {
|
||||
const used = parseSi(get(this,'requested.memory'));
|
||||
const total = parseSi(get(this,'allocatable.memory'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
}),
|
||||
|
||||
podUsage: computed('requested.pods','allocatable.pods', function() {
|
||||
const used = parseSi(get(this,'requested.pods'));
|
||||
const total = parseSi(get(this,'allocatable.pods'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1000, '', '', 0, minExp).replace(/\s.*$/,'');
|
||||
const totalStr = formatSi(total, 1000, '', '', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
podPercent: computed('requested.pods','allocatable.pods', function() {
|
||||
const used = parseSi(get(this,'requested.pods'));
|
||||
const total = parseSi(get(this,'allocatable.pods'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
return '('+get(this,'id')+')';
|
||||
}),
|
||||
|
||||
/*
|
||||
osBlurb: function() {
|
||||
var out = this.get('info.osInfo.operatingSystem')||'';
|
||||
var out = get(this,'info.osInfo.operatingSystem')||'';
|
||||
|
||||
out = out.replace(/\s+\(.*?\)/,''); // Remove details in parens
|
||||
out = out.replace(/;.*$/,''); // Or after semicolons
|
||||
out = out.replace('Red Hat Enterprise Linux Server','RHEL'); // That's kinda long
|
||||
|
||||
var hasKvm = (this.get('labels')||{})[C.LABEL.KVM] === 'true';
|
||||
var hasKvm = (get(this,'labels')||{})[C.LABEL.KVM] === 'true';
|
||||
if ( hasKvm && out )
|
||||
{
|
||||
out += ' (with KVM)';
|
||||
|
|
@ -190,19 +130,19 @@ var Machine = Resource.extend(StateCounts,{
|
|||
osDetail: alias('info.osInfo.operatingSystem'),
|
||||
|
||||
dockerEngineVersion: function() {
|
||||
if ( this.get('info.osInfo') )
|
||||
if ( get(this,'info.osInfo') )
|
||||
{
|
||||
*/
|
||||
// return (this.get('info.osInfo.dockerVersion')||'').replace(/^Docker version\s*/i,'').replace(/,.*/,'');
|
||||
// return (get(this,'info.osInfo.dockerVersion')||'').replace(/^Docker version\s*/i,'').replace(/,.*/,'');
|
||||
/* }
|
||||
}.property('info.osInfo.dockerVersion'),
|
||||
|
||||
supportState: function() {
|
||||
let my = this.get('dockerEngineVersion')||'';
|
||||
let my = get(this,'dockerEngineVersion')||'';
|
||||
my = my.replace(/-(cs|ce|ee)[0-9.-]*$/,'');
|
||||
|
||||
let supported = this.get(`settings.${C.SETTING.SUPPORTED_DOCKER}`);
|
||||
let newest = this.get(`settings.${C.SETTING.NEWEST_DOCKER}`);
|
||||
let supported = get(this,`settings.${C.SETTING.SUPPORTED_DOCKER}`);
|
||||
let newest = get(this,`settings.${C.SETTING.NEWEST_DOCKER}`);
|
||||
|
||||
if ( !my || !supported || !newest) {
|
||||
return 'unknown';
|
||||
|
|
@ -218,20 +158,20 @@ var Machine = Resource.extend(StateCounts,{
|
|||
dockerDetail: alias('info.osInfo.operatingSystem'),
|
||||
|
||||
kernelBlurb: function() {
|
||||
if ( this.get('info.osInfo') )
|
||||
if ( get(this,'info.osInfo') )
|
||||
{
|
||||
return (this.get('info.osInfo.kernelVersion')||'');
|
||||
return (get(this,'info.osInfo.kernelVersion')||'');
|
||||
}
|
||||
}.property('info.osInfo.kernelVersion'),
|
||||
|
||||
cpuBlurb: function() {
|
||||
if ( this.get('info.cpuInfo.count') )
|
||||
if ( get(this,'info.cpuInfo.count') )
|
||||
{
|
||||
var ghz = Math.round(this.get('info.cpuInfo.mhz')/10)/100;
|
||||
var ghz = Math.round(get(this,'info.cpuInfo.mhz')/10)/100;
|
||||
|
||||
if ( this.get('info.cpuInfo.count') > 1 )
|
||||
if ( get(this,'info.cpuInfo.count') > 1 )
|
||||
{
|
||||
return this.get('info.cpuInfo.count')+'x' + ghz + ' GHz';
|
||||
return get(this,'info.cpuInfo.count')+'x' + ghz + ' GHz';
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -243,22 +183,22 @@ var Machine = Resource.extend(StateCounts,{
|
|||
cpuTooltip: alias('info.cpuInfo.modelName'),
|
||||
|
||||
memoryBlurb: function() {
|
||||
if ( this.get('info.memoryInfo') )
|
||||
if ( get(this,'info.memoryInfo') )
|
||||
{
|
||||
return formatMib(this.get('info.memoryInfo.memTotal'));
|
||||
return formatMib(get(this,'info.memoryInfo.memTotal'));
|
||||
}
|
||||
}.property('info.memoryInfo.memTotal'),
|
||||
|
||||
memoryLimitBlurb: computed('memory', function() {
|
||||
if ( this.get('memory') )
|
||||
if ( get(this,'memory') )
|
||||
{
|
||||
return formatSi(this.get('memory'), 1024, 'iB', 'B');
|
||||
return formatSi(get(this,'memory'), 1024, 'iB', 'B');
|
||||
}
|
||||
}),
|
||||
|
||||
localStorageBlurb: computed('localStorageMb', function() {
|
||||
if (this.get('localStorageMb')) {
|
||||
return formatSi(this.get('localStorageMb'), 1024, 'iB', 'B', 2); // start at 1024^2==MB
|
||||
if (get(this,'localStorageMb')) {
|
||||
return formatSi(get(this,'localStorageMb'), 1024, 'iB', 'B', 2); // start at 1024^2==MB
|
||||
}
|
||||
}),
|
||||
|
||||
|
|
@ -266,19 +206,19 @@ var Machine = Resource.extend(StateCounts,{
|
|||
var totalMb = 0;
|
||||
|
||||
// New hotness
|
||||
if ( this.get('info.diskInfo.fileSystems') )
|
||||
if ( get(this,'info.diskInfo.fileSystems') )
|
||||
{
|
||||
var fses = this.get('info.diskInfo.fileSystems')||[];
|
||||
var fses = get(this,'info.diskInfo.fileSystems')||[];
|
||||
Object.keys(fses).forEach((fs) => {
|
||||
totalMb += fses[fs].capacity;
|
||||
});
|
||||
|
||||
return formatMib(totalMb);
|
||||
}
|
||||
else if ( this.get('info.diskInfo.mountPoints') )
|
||||
else if ( get(this,'info.diskInfo.mountPoints') )
|
||||
{
|
||||
// Old & busted
|
||||
var mounts = this.get('info.diskInfo.mountPoints')||[];
|
||||
var mounts = get(this,'info.diskInfo.mountPoints')||[];
|
||||
Object.keys(mounts).forEach((mountPoint) => {
|
||||
totalMb += mounts[mountPoint].total;
|
||||
});
|
||||
|
|
@ -289,10 +229,10 @@ var Machine = Resource.extend(StateCounts,{
|
|||
|
||||
diskDetail: function() {
|
||||
// New hotness
|
||||
if ( this.get('info.diskInfo.fileSystems') )
|
||||
if ( get(this,'info.diskInfo.fileSystems') )
|
||||
{
|
||||
var out = [];
|
||||
var fses = this.get('info.diskInfo.fileSystems')||[];
|
||||
var fses = get(this,'info.diskInfo.fileSystems')||[];
|
||||
Object.keys(fses).forEach((fs) => {
|
||||
out.pushObject(EmberObject.create({label: fs, value: formatMib(fses[fs].capacity)}));
|
||||
});
|
||||
|
|
@ -305,8 +245,8 @@ var Machine = Resource.extend(StateCounts,{
|
|||
// If you use this you must ensure that services and containers are already in the store
|
||||
// or they will not be pulled in correctly.
|
||||
displayEndpoints: function() {
|
||||
var store = this.get('clusterStore');
|
||||
return (this.get('publicEndpoints')||[]).map((endpoint) => {
|
||||
var store = get(this,'clusterStore');
|
||||
return (get(this,'publicEndpoints')||[]).map((endpoint) => {
|
||||
if ( !endpoint.service ) {
|
||||
endpoint.service = store.getById('service', endpoint.serviceId);
|
||||
}
|
||||
|
|
@ -317,7 +257,7 @@ var Machine = Resource.extend(StateCounts,{
|
|||
}.property('publicEndpoints.@each.{ipAddress,port,serviceId,instanceId}'),
|
||||
|
||||
requireAnyLabelStrings: function() {
|
||||
return ((this.get('labels')||{})[C.LABEL.REQUIRE_ANY]||'')
|
||||
return ((get(this,'labels')||{})[C.LABEL.REQUIRE_ANY]||'')
|
||||
.split(/\s*,\s*/)
|
||||
.filter((x) => x.length > 0 && x !== C.LABEL.SYSTEM_TYPE);
|
||||
}.property(`labels.${C.LABEL.REQUIRE_ANY}`),
|
||||
|
|
|
|||
|
|
@ -111,10 +111,10 @@ var machineDriver = Resource.extend(PolledResource, {
|
|||
return [
|
||||
{ label: 'action.edit', icon: 'icon icon-edit', action: 'edit', enabled: !!l.update && !builtin },
|
||||
{ divider: true },
|
||||
{ label: 'action.activate', icon: 'icon icon-play', action: 'activate', enabled: !!a.activate},
|
||||
{ label: 'action.deactivate', icon: 'icon icon-pause', action: 'deactivate', enabled: !!a.deactivate},
|
||||
{ label: 'action.activate', icon: 'icon icon-play', action: 'activate', enabled: !!a.activate, bulkable: true},
|
||||
{ label: 'action.deactivate', icon: 'icon icon-pause', action: 'deactivate', enabled: !!a.deactivate, bulkable: true},
|
||||
{ divider: true },
|
||||
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove && !builtin, altAction: 'delete'},
|
||||
{ label: 'action.remove', icon: 'icon icon-trash', action: 'promptDelete', enabled: !!l.remove && !builtin, altAction: 'delete', bulkable: true},
|
||||
{ divider: true },
|
||||
{ label: 'action.viewInApi', icon: 'icon icon-external-link',action: 'goToApi', enabled: true },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ import Resource from 'ember-api-store/models/resource';
|
|||
import { get, computed } from '@ember/object';
|
||||
|
||||
var User = Resource.extend({
|
||||
modalService: service('modal'),
|
||||
router: service(),
|
||||
|
||||
actions: {
|
||||
|
|
|
|||
|
|
@ -51,10 +51,14 @@ h6 {
|
|||
font-family : Consolas, "Andale Mono", "Lucida Console", Monaco, "Courier New", Courier, monospace;
|
||||
}
|
||||
|
||||
.no-inline-space {
|
||||
@mixin no-inline-space() {
|
||||
font-family: zerowidthspace;
|
||||
|
||||
& > * {
|
||||
font-family: $text-font-stack;
|
||||
}
|
||||
}
|
||||
|
||||
.no-inline-space {
|
||||
@include no-inline-space;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,6 +165,8 @@ fieldset[disabled] .btn {
|
|||
|
||||
//button group
|
||||
[class^='btn-group'] {
|
||||
@include no-inline-space;
|
||||
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
|
|
|
|||
|
|
@ -58,38 +58,6 @@
|
|||
as |al expandFn|
|
||||
}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'accountsPage.detail.table.project.title')
|
||||
detail=(t 'accountsPage.detail.table.project.description')
|
||||
expandOnInit=true
|
||||
expandAll=false
|
||||
expand=(action expandFn)
|
||||
}}
|
||||
{{#sortable-table
|
||||
classNames="grid sortable-table"
|
||||
body=projectRoles
|
||||
search=false
|
||||
sortBy=sortBy
|
||||
bulkActions=false
|
||||
pagingLabel="pagination.node"
|
||||
headers=projectHeaders as |sortable kind role dt|}}
|
||||
{{#if (eq kind "row")}}
|
||||
<tr class="main-row">
|
||||
<td data-title="{{dt.name}}" class="state">
|
||||
{{role.name}}
|
||||
</td>
|
||||
|
||||
<td data-title="{{dt.project.name}}">
|
||||
<a href="#" {{action 'launchOnCluster' role.project }}>{{role.project.name}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'accountsPage.detail.table.project.noRoles'}}</td></tr>
|
||||
{{/if}}
|
||||
{{/sortable-table}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'accountsPage.detail.table.cluster.title')
|
||||
detail=(t 'accountsPage.detail.table.cluster.description')
|
||||
|
|
@ -124,8 +92,36 @@
|
|||
{{/sortable-table}}
|
||||
{{/accordion-list-item}}
|
||||
|
||||
{{#accordion-list-item
|
||||
title=(t 'accountsPage.detail.table.project.title')
|
||||
detail=(t 'accountsPage.detail.table.project.description')
|
||||
expandOnInit=true
|
||||
expandAll=false
|
||||
expand=(action expandFn)
|
||||
}}
|
||||
{{#sortable-table
|
||||
classNames="grid sortable-table"
|
||||
body=projectRoles
|
||||
search=false
|
||||
sortBy=sortBy
|
||||
bulkActions=false
|
||||
pagingLabel="pagination.node"
|
||||
headers=projectHeaders as |sortable kind role dt|}}
|
||||
{{#if (eq kind "row")}}
|
||||
<tr class="main-row">
|
||||
<td data-title="{{dt.name}}" class="state">
|
||||
{{role.name}}
|
||||
</td>
|
||||
|
||||
<td data-title="{{dt.project.name}}">
|
||||
<a href="#" {{action 'launchOnCluster' role.project }}>{{role.project.name}}</a>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'accountsPage.detail.table.project.noRoles'}}</td></tr>
|
||||
{{/if}}
|
||||
{{/sortable-table}}
|
||||
{{/accordion-list-item}}
|
||||
{{/accordion-list}}
|
||||
|
||||
|
||||
</section>
|
||||
{{top-errors errors=errors}}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
<section class="header clearfix">
|
||||
<div class="pull-left"><h1>{{t 'accountsPage.index.header'}}</h1></div>
|
||||
|
||||
{{#if isLocal}}
|
||||
<div class="right-buttons">{{#link-to "accounts.new" classNames="btn btn-sm bg-primary right-divider-btn"}}{{t 'accountsPage.index.localLink'}}{{/link-to}}</div>
|
||||
{{/if}}
|
||||
<div class="right-buttons">{{#link-to "accounts.new" classNames="btn btn-sm bg-primary right-divider-btn"}}{{t 'accountsPage.index.localLink'}}{{/link-to}}</div>
|
||||
</section>
|
||||
|
||||
<section class="instances">
|
||||
|
|
|
|||
|
|
@ -1,12 +1,11 @@
|
|||
<section class="header clearfix">
|
||||
<h1 class="pull-left">{{t 'catalogSettings.header'}}</h1>
|
||||
|
||||
<div class="right-buttons">
|
||||
<button class="btn bg-link icon-btn" {{action "add"}}>
|
||||
<span class="darken"><i class="icon icon-plus text-small"/></span>
|
||||
<span>{{t 'catalogSettings.more.addActionLabel'}}</span>
|
||||
<button class="btn bg-primary btn-sm" {{action "add"}}>
|
||||
{{t 'catalogSettings.more.addActionLabel'}}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<h1>{{t 'catalogSettings.header'}}</h1>
|
||||
</section>
|
||||
|
||||
<div class="row row-same-height">
|
||||
|
|
@ -14,11 +13,17 @@
|
|||
<h2>{{t (if settings.isRancher 'catalogSettings.certified.header.rancher' 'catalogSettings.certified.header.pl') appName=settings.appName}}</h2>
|
||||
<div>
|
||||
{{#if stdLibrary}}
|
||||
<button class="btn btn-link btn-sm bg-success" {{action "disableLibrary"}}>{{t 'generic.enabled'}}</button>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableLibrary"}}>{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-success">{{t 'generic.enabled'}}</button>
|
||||
</div>
|
||||
{{else if libraryUsed}}
|
||||
{{t 'catalogSettings.notAvailable' name='library'}}
|
||||
{{else}}
|
||||
<button class="btn btn-link btn-sm bg-primary" {{action "enableLibrary"}}>{{t 'generic.disabled'}}</button>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm bg-primary">{{t 'generic.disabled'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableLibrary"}}>{{t 'generic.enable'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<p class="text-info">
|
||||
|
|
@ -30,11 +35,17 @@
|
|||
<h2>{{t (if settings.isRancher 'catalogSettings.community.header.rancher' 'catalogSettings.community.header.pl') appName=settings.appName}}</h2>
|
||||
<div>
|
||||
{{#if stdCommunity}}
|
||||
<button class="btn btn-link btn-sm bg-success" {{action "disableCommunity"}}>{{t 'generic.enabled'}}</button>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm bg-default" {{action "disableCommunity"}}>{{t 'generic.disable'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-success">{{t 'generic.enabled'}}</button>
|
||||
</div>
|
||||
{{else if communityUsed}}
|
||||
{{t 'catalogSettings.notAvailable' name='community'}}
|
||||
{{else}}
|
||||
<button class="btn btn-link btn-sm bg-primary" {{action "enableCommunity"}}>{{t 'generic.disabled'}}</button>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-link btn-sm bg-primary">{{t 'generic.disabled'}}</button>
|
||||
<button class="btn btn-link btn-sm bg-defualt" {{action "enableCommunity"}}>{{t 'generic.enable'}}</button>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
<p class="text-info">
|
||||
|
|
|
|||
|
|
@ -19,28 +19,24 @@ const headers = [
|
|||
sort: ['numHosts','name','id'],
|
||||
translationKey: 'clustersPage.hosts.label',
|
||||
width: 100,
|
||||
classNames: 'text-center',
|
||||
},
|
||||
{
|
||||
name: 'cpu',
|
||||
sort: ['numGhz','name','id'],
|
||||
translationKey: 'clustersPage.cpu.label',
|
||||
width: 100,
|
||||
classNames: 'text-center',
|
||||
},
|
||||
{
|
||||
name: 'memory',
|
||||
sort: ['numMem','name','id'],
|
||||
translationKey: 'clustersPage.memory.label',
|
||||
width: 100,
|
||||
classNames: 'text-center',
|
||||
},
|
||||
{
|
||||
name: 'storage',
|
||||
sort: ['numStorage','name','id'],
|
||||
translationKey: 'clustersPage.storage.label',
|
||||
width: 100,
|
||||
classNames: 'text-center',
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
<h1 class="pull-left">{{t 'clustersPage.header'}}</h1> <div class="vertical-middle"></div>
|
||||
|
||||
<div class="right-buttons">
|
||||
{{#link-to "clusters.new" class="btn bg-primary btn-sm icon-btn"}}
|
||||
<span class="darken"><i class="icon icon-cluster"></i></span>
|
||||
<span>{{t 'clustersPage.newCluster'}}</span>
|
||||
{{#link-to "clusters.new" class="btn btn-sm bg-primary"}}
|
||||
{{t 'clustersPage.newCluster'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,23 @@ export default Controller.extend({
|
|||
globalStore: service(),
|
||||
modalService: service('modal'),
|
||||
|
||||
headers: [
|
||||
{
|
||||
name: 'state',
|
||||
sort: ['sortState','displayName'],
|
||||
searchField: 'displayState',
|
||||
translationKey: 'generic.state',
|
||||
width: 120
|
||||
},
|
||||
{
|
||||
name: 'name',
|
||||
sort: ['displayName'],
|
||||
searchField: 'displayName',
|
||||
translationKey: 'generic.name',
|
||||
|
||||
},
|
||||
],
|
||||
|
||||
actions: {
|
||||
activate(driver) {
|
||||
let action = null;
|
||||
|
|
@ -73,7 +90,7 @@ export default Controller.extend({
|
|||
};
|
||||
},
|
||||
|
||||
arranged: computed('model.drivers.@each.{state,id,version,externalId}', 'model.catalogDrivers.@each.{id,catalogId,name}', function() {
|
||||
rows: computed('model.drivers.@each.{state,id,version,externalId}', 'model.catalogDrivers.@each.{id,catalogId,name}', function() {
|
||||
// possibly add some search here
|
||||
let cDrivers = this.get('model.catalogDrivers.catalog');
|
||||
let drivers = this.get('model.drivers.content');
|
||||
|
|
@ -98,6 +115,6 @@ export default Controller.extend({
|
|||
});
|
||||
|
||||
newContent = newContent.concat(drivers);
|
||||
return newContent.sortBy('name');
|
||||
return newContent;
|
||||
}),
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,67 +1,51 @@
|
|||
<section class="header clearfix">
|
||||
<h1 class="pull-left">{{t 'machinePage.header'}}</h1> <div class="vertical-middle"></div>
|
||||
<p>{{t 'machinePage.subtext' htmlSafe=true}}</p>
|
||||
|
||||
<div class="right-buttons">
|
||||
<button class="btn btn-sm bg-primary right-divider-btn" {{action 'addNewDriver'}}>{{t 'machinePage.add'}}</button>
|
||||
</div>
|
||||
|
||||
<h1>{{t 'machinePage.header'}}</h1> <div class="vertical-middle"></div>
|
||||
</section>
|
||||
|
||||
<section class="pl-15 pr-15 clearfix">
|
||||
{{#each arranged as |driver|}}
|
||||
{{#catalog-box
|
||||
model=driver
|
||||
active=(not (or (eq driver.state 'inactive') (eq driver.type 'template')))
|
||||
classNames='machine'
|
||||
showIcon=false
|
||||
showDescription=false
|
||||
as |section|
|
||||
}}
|
||||
{{#if (eq section 'header')}}
|
||||
<div class="catalog-header bg-default clearfix p-5">
|
||||
{{#if driver.state}}
|
||||
{{badge-state model=driver class="pull-left vertical-middle btn-xs"}}
|
||||
{{else}}
|
||||
<span class="state badge-state btn-xs text-danger bg-error pull-left">
|
||||
<i class="icon icon-circle"></i> {{t 'machinePage.inactive'}}
|
||||
</span>
|
||||
{{/if}}
|
||||
{{#sortable-table
|
||||
classNames="grid sortable-table"
|
||||
body=rows
|
||||
searchText=searchText
|
||||
sortBy=sortBy
|
||||
bulkActions=true
|
||||
pagingLabel="pagination.driver"
|
||||
headers=headers as |sortable kind driver dt|}}
|
||||
{{#if (eq kind "row")}}
|
||||
<tr class="main-row">
|
||||
<td valign="middle" class="row-check" style="padding-top: 2px;">
|
||||
{{check-box nodeId=driver.id}}
|
||||
</td>
|
||||
|
||||
{{#if driver.catalogId}}
|
||||
<div class=" btn-group resource-actions action-menu pull-right">
|
||||
{{#tooltip-element inlineBlock=true type="tooltip-basic" tooltipTemplate="tooltip-static" model=(t 'generic.activate') tagName="span" tooltipFor="catalogMachine"}}
|
||||
<button class="btn bg-default btn-sm" aria-label={{t 'generic.activate'}} {{action 'addCatalogDriver' driver}}>
|
||||
<i class="icon-fw icon icon-play" alt={{t 'generic.activate'}}></i>
|
||||
</button>
|
||||
{{/tooltip-element~}}
|
||||
</div>
|
||||
<td data-title="{{dt.state}}" class="state">
|
||||
{{badge-state model=driver}}
|
||||
</td>
|
||||
|
||||
<td data-title="{{dt.name}}" class="clip">
|
||||
{{driver.displayName}}
|
||||
<div class="clip text-small">
|
||||
{{#if driver.builtin}}
|
||||
<span class="text-muted">{{t 'machinePage.builtin'}}</span>
|
||||
{{else}}
|
||||
{{action-menu model=driver class="pull-right"}}
|
||||
{{driver.url}}
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if driver.externalId}}
|
||||
{{log driver.catalogTemplateIcon}}
|
||||
<div class="catalog-icon m-20" style="background-image:url({{driver.catalogTemplateIcon}});"/>
|
||||
{{else if driver.machineHasIcon}}
|
||||
{{log driver.machineHasIcon}}
|
||||
<div class="catalog-icon m-20" style="background-image:url({{driver.machineHasIcon}});"/>
|
||||
{{else}}
|
||||
<div class="catalog-icon m-20 {{driver.displayIcon}}"/>
|
||||
{{/if}}
|
||||
{{else if (eq section 'body')}}
|
||||
<div class="{{if (eq driver.state 'active') 'text-bold'}}">
|
||||
{{driver.name}}
|
||||
</div>
|
||||
<div class="m-10 description">{{driver.description}}</div>
|
||||
{{else if (eq section 'footer')}}
|
||||
{{#if (and driver.externalId (not-eq driver.state 'inactive'))}}
|
||||
{{upgrade-dropdown model=driver btnClass="btn-sm" currentId=driver.externalId upgradeOnly=false changeVersion=(action "upgradeDriver" driver)}}
|
||||
{{else if driver.builtin}}
|
||||
<span class="text-muted">{{t 'machinePage.builtin'}}</span>
|
||||
{{/if}}
|
||||
</td>
|
||||
|
||||
{{/if}}
|
||||
<td data-title="{{dt.actions}}" class="actions">
|
||||
{{action-menu model=driver}}
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
{{/catalog-box}}
|
||||
{{/each}}
|
||||
</section>
|
||||
{{#if model.showTransitioningMessage}}
|
||||
{{error-sub-row fullColspan=sortable.fullColspan model=driver}}
|
||||
{{/if}}
|
||||
{{else if (eq kind "nomatch")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'nodesPage.table.noMatch'}}</td></tr>
|
||||
{{else if (eq kind "norows")}}
|
||||
<tr><td colspan="{{sortable.fullColspan}}" class="text-center text-muted pt-20 pb-20">{{t 'nodesPage.table.noData'}}</td></tr>
|
||||
{{/if}}
|
||||
{{/sortable-table}}
|
||||
|
|
|
|||
|
|
@ -2,9 +2,8 @@
|
|||
<h1 class="pull-left">{{t 'nodesPage.header'}}</h1> <div class="vertical-middle"></div>
|
||||
|
||||
<div class="right-buttons">
|
||||
{{#link-to "machines.templates" class="btn bg-primary btn-sm icon-btn"}}
|
||||
<span class="darken"><i class="icon icon-plus"></i></span>
|
||||
<span>{{t 'nodesPage.addNode'}}</span>
|
||||
{{#link-to "machines.templates" class="btn bg-primary btn-sm"}}
|
||||
{{t 'nodesPage.addNode'}}
|
||||
{{/link-to}}
|
||||
</div>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -36,23 +36,20 @@
|
|||
{{/if}}
|
||||
</td>
|
||||
{{else}}
|
||||
<td colspan="4" class="text-center text-muted">
|
||||
Counts Coming Soon
|
||||
<td data-title="{{dt.hosts}}">
|
||||
{{model.machines.length}}
|
||||
</td>
|
||||
<!--
|
||||
<td data-title="{{dt.hosts}}" class="text-center">
|
||||
{{model.numHosts}}
|
||||
<td data-title="{{dt.cpu}}">
|
||||
{{model.cpuUsage}}
|
||||
</td>
|
||||
<td data-title="{{dt.cpu}}" class="text-center">
|
||||
{{model.numGhz}} GHz
|
||||
|
||||
<td data-title="{{dt.memory}}">
|
||||
{{model.memoryUsage}}
|
||||
</td>
|
||||
<td data-title="{{dt.memory}}" class="text-center">
|
||||
{{model.numMem}} GiB
|
||||
|
||||
<td data-title="{{dt.pod}}">
|
||||
{{model.podUsage}}
|
||||
</td>
|
||||
<td data-title="{{dt.storage}}" class="text-center">
|
||||
{{model.numStorage}} GiB
|
||||
</td>
|
||||
-->
|
||||
{{/if}}
|
||||
<td data-title="{{dt.actions}} "class="actions">
|
||||
{{action-menu model=model}}
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ export const headersAll = [
|
|||
name: 'cpu',
|
||||
sort: ['cpu','displayName'],
|
||||
searchField: null,
|
||||
width: 120,
|
||||
width: 100,
|
||||
translationKey: 'nodesPage.table.cpu',
|
||||
views: ['cluster','global'],
|
||||
},
|
||||
|
|
@ -51,7 +51,7 @@ export const headersAll = [
|
|||
name: 'pod',
|
||||
sort: false,
|
||||
searchField: null,
|
||||
width: 120,
|
||||
width: 100,
|
||||
translationKey: 'nodesPage.table.pod',
|
||||
views: ['cluster','global'],
|
||||
},
|
||||
|
|
|
|||
|
|
@ -0,0 +1,66 @@
|
|||
import Mixin from '@ember/object/mixin';
|
||||
import { get, computed } from '@ember/object';
|
||||
import { formatPercent } from 'shared/utils/util';
|
||||
import { formatSi, parseSi, exponentNeeded } from 'shared/utils/parse-unit';
|
||||
|
||||
export default Mixin.create({
|
||||
cpuUsage: computed('requested.cpu','allocatable.cpu', function() {
|
||||
const used = parseSi(get(this,'requested.cpu'));
|
||||
const total = parseSi(get(this,'allocatable.cpu'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1000, '', '', 0, minExp).replace(/\s.*$/,'');
|
||||
const totalStr = formatSi(total, 1000, '', '', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
cpuPercent: computed('requested.cpu','allocatable.cpu', function() {
|
||||
const used = parseSi(get(this,'requested.cpu'));
|
||||
const total = parseSi(get(this,'allocatable.cpu'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
}),
|
||||
|
||||
memoryUsage: computed('requested.memory','allocatable.memory', function() {
|
||||
const used = parseSi(get(this,'requested.memory'));
|
||||
const total = parseSi(get(this,'allocatable.memory'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1024, '', '', 0, minExp).replace(/\s.*/,'');
|
||||
const totalStr = formatSi(total, 1024, 'iB', 'B', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
memoryPercent: computed('requested.memory','allocatable.memory', function() {
|
||||
const used = parseSi(get(this,'requested.memory'));
|
||||
const total = parseSi(get(this,'allocatable.memory'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
}),
|
||||
|
||||
podUsage: computed('requested.pods','allocatable.pods', function() {
|
||||
const used = parseSi(get(this,'requested.pods'));
|
||||
const total = parseSi(get(this,'allocatable.pods'));
|
||||
if ( total ) {
|
||||
const minExp = exponentNeeded(total);
|
||||
const usedStr = formatSi(used, 1000, '', '', 0, minExp).replace(/\s.*$/,'');
|
||||
const totalStr = formatSi(total, 1000, '', '', 0, minExp);
|
||||
|
||||
return `${usedStr}/${totalStr}`
|
||||
}
|
||||
}),
|
||||
|
||||
podPercent: computed('requested.pods','allocatable.pods', function() {
|
||||
const used = parseSi(get(this,'requested.pods'));
|
||||
const total = parseSi(get(this,'allocatable.pods'));
|
||||
if ( total ) {
|
||||
return formatPercent(100*used/total);
|
||||
}
|
||||
}),
|
||||
});
|
||||
|
|
@ -1087,6 +1087,7 @@ machinePage:
|
|||
subtext: "Additional <code>docker-machine</code> drivers can be loaded here and used in the Add Node screen."
|
||||
add: Add Node Driver
|
||||
builtin: Built-In
|
||||
url: Location
|
||||
|
||||
# If you change translations here also change the translation in app/utils/constants.js under the FALLBACK_TRANSLATIONS key
|
||||
# those are present in case we have an error in the app and can not load the translations file
|
||||
|
|
@ -3904,6 +3905,11 @@ pagination:
|
|||
=0 {No DNS Records}
|
||||
=1 {{count} {count, plural, =1 {DNS Record} other {DNS Records}}}
|
||||
other {{from} - {to} of {count} DNS Records}}
|
||||
driver: |
|
||||
{pages, plural,
|
||||
=0 {No Drivers}
|
||||
=1 {{count} {count, plural, =1 {Driver} other {Drivers}}}
|
||||
other {{from} - {to} of {count} Drivers}}
|
||||
driverOptions: |
|
||||
{pages, plural,
|
||||
=0 {No Options}
|
||||
|
|
|
|||
Loading…
Reference in New Issue