Merge pull request #21128 from ricardoasmarques/wip-usage-bar

mgr/dashboard: Add usage bar component

Reviewed-by: Tiago Melo <tmelo@suse.com>
Reviewed-by: Volker Theile <vtheile@suse.com>
This commit is contained in:
Lenz Grimmer 2018-04-06 11:07:01 +02:00 committed by GitHub
commit 658e5d5a50
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 117 additions and 19 deletions

View File

@ -55,11 +55,9 @@
</div>
<!-- templates -->
<ng-template #poolProgressTmpl
<ng-template #poolUsageTpl
let-row="row">
<progressbar type="danger"
[value]="row.used * 100.0 / row.avail">
</progressbar>
<cd-usage-bar [totalBytes]="row.size" [usedBytes]="row.used"></cd-usage-bar>
</ng-template>
<ng-template #activityTmpl

View File

@ -14,7 +14,7 @@ import { CephfsService } from '../cephfs.service';
styleUrls: ['./cephfs.component.scss']
})
export class CephfsComponent implements OnInit, OnDestroy {
@ViewChild('poolProgressTmpl') poolProgressTmpl: TemplateRef<any>;
@ViewChild('poolUsageTpl') poolUsageTpl: TemplateRef<any>;
@ViewChild('activityTmpl') activityTmpl: TemplateRef<any>;
routeParamsSubscribe: Subscription;
@ -54,11 +54,10 @@ export class CephfsComponent implements OnInit, OnDestroy {
columns: [
{ prop: 'pool' },
{ prop: 'type' },
{ prop: 'used', pipe: this.dimlessBinary },
{ prop: 'avail', pipe: this.dimlessBinary },
{ prop: 'size', pipe: this.dimlessBinary },
{
name: 'Usage',
cellTemplate: this.poolProgressTmpl,
cellTemplate: this.poolUsageTpl,
comparator: (valueA, valueB, rowA, rowB, sortDirection) => {
const valA = rowA.used / rowA.avail;
const valB = rowB.used / rowB.avail;
@ -96,6 +95,9 @@ export class CephfsComponent implements OnInit, OnDestroy {
this.cephfsService.getCephfs(this.id).subscribe((data: any) => {
this.ranks.data = data.cephfs.ranks;
this.pools.data = data.cephfs.pools;
this.pools.data.forEach((pool) => {
pool.size = pool.used + pool.avail;
});
this.standbys = [
{
key: 'Standby daemons',

View File

@ -23,3 +23,8 @@
<!-- Has to be on the same line to prevent a space between state and comma. -->
</span>
</ng-template>
<ng-template #osdUsageTpl
let-row="row">
<cd-usage-bar [totalBytes]="row.stats.stat_bytes" [usedBytes]="row.stats.stat_bytes_used"></cd-usage-bar>
</ng-template>

View File

@ -3,6 +3,7 @@ import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TabsModule } from 'ngx-bootstrap/tabs';
import { ComponentsModule } from '../../../../shared/components/components.module';
import { DataTableModule } from '../../../../shared/datatable/datatable.module';
import { DimlessPipe } from '../../../../shared/pipes/dimless.pipe';
import { FormatterService } from '../../../../shared/services/formatter.service';
@ -24,7 +25,8 @@ describe('OsdListComponent', () => {
HttpClientModule,
PerformanceCounterModule,
TabsModule.forRoot(),
DataTableModule
DataTableModule,
ComponentsModule
],
declarations: [
OsdListComponent,

View File

@ -3,7 +3,7 @@ import { Component, OnInit, TemplateRef, ViewChild } from '@angular/core';
import { CellTemplate } from '../../../../shared/enum/cell-template.enum';
import { CdTableColumn } from '../../../../shared/models/cd-table-column';
import { CdTableSelection } from '../../../../shared/models/cd-table-selection';
import { DimlessPipe } from '../../../../shared/pipes/dimless.pipe';
import { DimlessBinaryPipe } from '../../../../shared/pipes/dimless-binary.pipe';
import { OsdService } from '../osd.service';
@Component({
@ -14,6 +14,7 @@ import { OsdService } from '../osd.service';
export class OsdListComponent implements OnInit {
@ViewChild('statusColor') statusColor: TemplateRef<any>;
@ViewChild('osdUsageTpl') osdUsageTpl: TemplateRef<any>;
osds = [];
columns: CdTableColumn[];
@ -21,7 +22,7 @@ export class OsdListComponent implements OnInit {
constructor(
private osdService: OsdService,
private dimlessPipe: DimlessPipe
private dimlessBinaryPipe: DimlessBinaryPipe
) { }
ngOnInit() {
@ -30,7 +31,8 @@ export class OsdListComponent implements OnInit {
{prop: 'id', name: 'ID', cellTransformation: CellTemplate.bold},
{prop: 'collectedStates', name: 'Status', cellTemplate: this.statusColor},
{prop: 'stats.numpg', name: 'PGs'},
{prop: 'usedPercent', name: 'Usage'},
{prop: 'stats.stat_bytes', name: 'Size', pipe: this.dimlessBinaryPipe},
{name: 'Usage', cellTemplate: this.osdUsageTpl},
{
prop: 'stats_history.out_bytes',
name: 'Read bytes',
@ -57,8 +59,6 @@ export class OsdListComponent implements OnInit {
osd.collectedStates = this.collectStates(osd);
osd.stats_history.out_bytes = osd.stats_history.op_out_bytes.map(i => i[1]);
osd.stats_history.in_bytes = osd.stats_history.op_in_bytes.map(i => i[1]);
osd.usedPercent = this.dimlessPipe.transform(osd.stats.stat_bytes_used) + ' / ' +
this.dimlessPipe.transform(osd.stats.stat_bytes);
return osd;
});
});

View File

@ -147,7 +147,7 @@
{{ pool.pg_status | pgStatus }}
</td>
<td>
{{ pool.stats.bytes_used.latest | dimlessBinary }} / {{ pool.stats.max_avail.latest | dimlessBinary }}
<cd-usage-bar [totalBytes]="pool.stats.bytes_used.latest + pool.stats.max_avail.latest" [usedBytes]="pool.stats.bytes_used.latest"></cd-usage-bar>
</td>
<td>
{{ pool.stats.rd_bytes.rate | dimless }}

View File

@ -2,11 +2,13 @@ import { CommonModule } from '@angular/common';
import { NgModule } from '@angular/core';
import { ChartsModule } from 'ng2-charts/ng2-charts';
import { AlertModule, PopoverModule } from 'ngx-bootstrap';
import { AlertModule, PopoverModule, TooltipModule } from 'ngx-bootstrap';
import { PipesModule } from '../pipes/pipes.module';
import { HelperComponent } from './helper/helper.component';
import { SparklineComponent } from './sparkline/sparkline.component';
import { SubmitButtonComponent } from './submit-button/submit-button.component';
import { UsageBarComponent } from './usage-bar/usage-bar.component';
import { ViewCacheComponent } from './view-cache/view-cache.component';
@NgModule({
@ -14,20 +16,24 @@ import { ViewCacheComponent } from './view-cache/view-cache.component';
CommonModule,
AlertModule.forRoot(),
PopoverModule.forRoot(),
ChartsModule
TooltipModule.forRoot(),
ChartsModule,
PipesModule
],
declarations: [
ViewCacheComponent,
SparklineComponent,
HelperComponent,
SubmitButtonComponent
SubmitButtonComponent,
UsageBarComponent
],
providers: [],
exports: [
ViewCacheComponent,
SparklineComponent,
HelperComponent,
SubmitButtonComponent
SubmitButtonComponent,
UsageBarComponent
]
})
export class ComponentsModule { }

View File

@ -0,0 +1,26 @@
<ng-template #usageTooltipTpl>
<table>
<tr>
<td class="text-left">Used:&nbsp;</td>
<td class="text-right"><strong> {{ usedBytes | dimlessBinary }}</strong></td>
</tr>
<tr>
<td class="text-left">Free:&nbsp;</td>
<td class="'text-right"><strong>{{ freeBytes | dimlessBinary }}</strong></td>
</tr>
</table>
</ng-template>
<div class="progress oaprogress"
data-placement="left"
[tooltip]="usageTooltipTpl">
<div class="progress-bar progress-bar-info"
role="progressbar"
[style.width]="usedPercentage + '%'">
<span>{{ usedPercentage }}%</span>
</div>
<div class="progress-bar progress-bar-freespace"
role="progressbar"
[style.width]="freePercentage + '%'">
</div>
</div>

View File

@ -0,0 +1,34 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { TooltipModule } from 'ngx-bootstrap';
import { PipesModule } from '../../pipes/pipes.module';
import { ServicesModule } from '../../services/services.module';
import { UsageBarComponent } from './usage-bar.component';
describe('UsageBarComponent', () => {
let component: UsageBarComponent;
let fixture: ComponentFixture<UsageBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
PipesModule,
ServicesModule,
TooltipModule.forRoot()
],
declarations: [ UsageBarComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UsageBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,25 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core';
@Component({
selector: 'cd-usage-bar',
templateUrl: './usage-bar.component.html',
styleUrls: ['./usage-bar.component.scss']
})
export class UsageBarComponent implements OnChanges {
@Input() totalBytes: number;
@Input() usedBytes: number;
usedPercentage: number;
freePercentage: number;
freeBytes: number;
constructor() { }
ngOnChanges() {
this.usedPercentage = Math.round(this.usedBytes / this.totalBytes * 100);
this.freePercentage = 100 - this.usedPercentage;
this.freeBytes = this.totalBytes - this.usedBytes;
}
}