Skip to content
Snippets Groups Projects
Commit 15cec7a5 authored by Sekina's avatar Sekina
Browse files

Charts and Stats in Dashboard

parent 80f2bf7a
Branches graphs_charts
No related tags found
No related merge requests found
Showing
with 117 additions and 152 deletions
......@@ -4,14 +4,15 @@
<div class="col-md-12">
<img [src]="bannerPath" width="100%">
</div>
<div class="row">
<div class="row charts">
<div class="col col-sm-6">
<div class="card mb-3">
<div class="card-header">
<h3 style="text-align: center">Blabla header</h3>
<h3 style="text-align: center">Ressources</h3>
</div>
<div class="card-body table-responsive">
<ngx-charts-pie-chart [view]="view" [results]="single" [doughnut]="true" [legend]="true" [labels]="true" (select)="onSelect($event)">
<ngx-charts-pie-chart [view]="view" [scheme]="colorScheme" [tooltipDisabled]="false" [results]="rssState" [legend]="true"
[labels]="true" (select)="onSelect($event)">
</ngx-charts-pie-chart>
</div>
<div class="card-footer">
......@@ -19,4 +20,38 @@
</div>
</div>
</div>
<div class="col col-sm-4">
<div class="card mb-3">
<div class="card-body">
<div class="row">
<div class="col col-xs-3">
<i class="fa fa-tasks fa-5x" style="color: #9998a4"></i>
</div>
<div class="col col-xs-9 text-right">
<div style="font-size: 75px">{{ nbJobCurrent }}</div>
<h3>Running Jobs</h3>
</div>
</div>
</div>
<div class="card-footer">
<button class="btn btn-info btn-sm">View</button>
</div>
</div>
<div class="card mb-3">
<div class="card-body">
<div class="row">
<div class="col col-xs-3">
<i class="fa fa-server fa-5x" style="color: #9998a4"></i>
</div>
<div class="col col-xs-9 text-right">
<div style="font-size: 75px">{{ nbRssTotal }}</div>
<h3>Resources available</h3>
</div>
</div>
</div>
<div class="card-footer">
<button class="btn btn-info btn-sm">View</button>
</div>
</div>
</div>
</div>
.charts {
align-content: center;
justify-content: space-around;
padding-top: 20px;
padding-bottom: 20px;
}
......@@ -9,22 +9,27 @@ import { ChartsService } from '../../shared/services/charts/charts.service';
})
export class DashboardComponent implements OnInit {
public single = [
public rssState = [
{
'name': 'Available',
'name': 'Free',
'value': 0
},
{
}, {
'name': 'Busy',
'value': 0
}
];
public nbRssAvailable: number;
public nbRssBusy: number;
public nbRssTotal = 0;
public nbJobCurrent = 0;
public colorScheme = {
domain: ['#78b3d0', '#c76a6a']
};
public colorScheme2 = {
domain: ['#9291a1']
};
view: any[] = [600, 400];
public view: any[] = [600, 400];
bannerPath = 'assets/images/banner.jpg';
public bannerPath = 'assets/images/banner.jpg';
constructor(private charts: ChartsService) {
}
......@@ -36,14 +41,20 @@ export class DashboardComponent implements OnInit {
ngOnInit() {
this.charts.getnbRssBusyObs().subscribe(
res => {
this.single[1].value = res;
this.single = [...this.single];
this.rssState[1].value = res;
this.rssState = [...this.rssState];
}
);
this.charts.getnbRssTotalObs().subscribe(
res => {
this.nbRssTotal = res;
this.rssState[0].value = res - this.rssState[1].value;
this.rssState = [...this.rssState];
}
);
this.charts.getnbRssAvailableObs().subscribe(
this.charts.getnbJobCurrentObs().subscribe(
res => {
this.single[0].value = res;
this.single = [...this.single];
this.nbJobCurrent = res;
}
);
}
......
......@@ -39,7 +39,7 @@
<!-- COL 2 -->
<div class="col-lg-6 col-xs-12">
<div class="form-group">
<label for="properties">Constraints to properties for the job</label>
<label for="properties">Optional constraints on job properties</label>
<input type="text" class="form-control" [(ngModel)]="job.properties" id="properties" name="properties">
<small class="form-text text-muted">Format is a WHERE clause from the SQL syntax (ex: not host like 'nodename.%') </small>
</div>
......
......@@ -37,7 +37,6 @@ export class JobEvent {
* TODO : Description Job
*/
export class Job {
public json: any;
public api_timestamp: string;
public array_id: number;
public array_index: number;
......@@ -124,8 +123,6 @@ export class Job {
}
this.json = input;
return this;
}
......
export * from './page-header/page-header.module';
export * from './stat/stat.module';
<div class="card text-white bg-{{bgClass}}">
<div class="card-header">
<div class="row">
<div class="col col-xs-3">
<i class="fa {{icon}} fa-5x"></i>
</div>
<div class="col col-xs-9 text-right">
<div class="d-block huge">{{count}}</div>
<div class="d-block">{{label}}</div>
</div>
</div>
</div>
<div class="card-footer">
<span class="float-left">View Details {{data}}</span>
<a href="javascript:void(0)" class="float-right card-inverse">
<span ><i class="fa fa-arrow-circle-right"></i></span>
</a>
</div>
</div>
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { StatComponent } from './stat.component';
describe('StatComponent', () => {
let component: StatComponent;
let fixture: ComponentFixture<StatComponent>;
beforeEach(
async(() => {
TestBed.configureTestingModule({
declarations: [StatComponent]
}).compileComponents();
})
);
beforeEach(() => {
fixture = TestBed.createComponent(StatComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-stat',
templateUrl: './stat.component.html',
styleUrls: ['./stat.component.scss']
})
export class StatComponent implements OnInit {
@Input() bgClass: string;
@Input() icon: string;
@Input() count: number;
@Input() label: string;
@Input() data: number;
@Output() event: EventEmitter<any> = new EventEmitter();
constructor() {}
ngOnInit() {}
}
import { StatModule } from './stat.module';
describe('StatModule', () => {
let statModule: StatModule;
beforeEach(() => {
statModule = new StatModule();
});
it('should create an instance', () => {
expect(statModule).toBeTruthy();
});
});
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { StatComponent } from './stat.component';
@NgModule({
imports: [CommonModule],
declarations: [StatComponent],
exports: [StatComponent]
})
export class StatModule {}
......@@ -3,47 +3,58 @@ import { OarApiService } from '../oar-api/oar-api.service';
import { Job, Resource } from '../../models';
import { JobsStore } from '../../stores';
import { Observable, BehaviorSubject } from 'rxjs/Rx';
import { List } from 'immutable';
@Injectable()
export class ChartsService {
private _nbRssAvailable: BehaviorSubject<number>;
/**
* Number of resources available in total
* @private
* @type {BehaviorSubject<number>}
* @memberof ChartsService
*/
private _nbRssTotal: BehaviorSubject<number>;
/**
* Number of resources used
* @private
* @type {BehaviorSubject<number>}
* @memberof ChartsService
*/
private _nbRssBusy: BehaviorSubject<number>;
private currentJobs: Job[];
private currentRss: Resource[];
private _nbJobCurrent: BehaviorSubject<number>;
private jobStoreArray: Job[];
private currentRss: Resource[];
constructor(private oarApi: OarApiService, private jobStore: JobsStore) {
this._nbRssAvailable = new BehaviorSubject<number>(0);
this._nbRssTotal = new BehaviorSubject<number>(0);
this._nbRssBusy = new BehaviorSubject<number>(0);
/* this.oarApi.getCurrentJobs().subscribe(
jobs => {
this._nbRssBusy.next(0);
this.currentJobs = jobs['items'];
console.log(jobs);
this.currentJobs.forEach(
job => {
console.log(job);
this._nbJobCurrent = new BehaviorSubject<number>(0);
this.initnbRssTotal();
this.initNbRssBusy();
}
this.oarApi.getJobResources(job.id.toString()).subscribe(
data => {
this._nbRssBusy.next(this.nbRssBusy + data['items'].length);
}
);
private initnbRssTotal() {
this.oarApi.getResources().subscribe(
rss => {
this._nbRssTotal.next(0);
this.currentRss = rss['items'];
this.currentRss.forEach(item => {
if (item.state === 'Alive' && item.api_timestamp < item.available_upto) {
this._nbRssTotal.next(this.nbRssTotal + 1);
}
);
});
}
);*/
);
}
private initNbRssBusy() {
this.jobStore.jobs.subscribe(
jobs => {
this._nbRssBusy.next(0);
this.jobStoreArray = jobs.toArray();
this.jobStoreArray.forEach(
this._nbJobCurrent.next(0);
jobs.toArray().forEach(
job => {
// If the job is using the resources
if (job.state === 'Launching' || job.state === 'Finishing' ||
......@@ -54,43 +65,36 @@ export class ChartsService {
this._nbRssBusy.next(this.nbRssBusy + data['items'].length);
}
);
this._nbJobCurrent.next(this.nbJobCurrent + 1);
}
}
);
}
);
this.oarApi.getResources().subscribe(
rss => {
console.log(rss);
this._nbRssAvailable.next(0);
this.currentRss = rss['items'];
this.currentRss.forEach(item => {
if (item.state === 'Alive') {
this._nbRssAvailable.next(this.nbRssAvailable + 1);
}
});
}
);
}
getnbRssAvailableObs(): Observable<number> {
return this._nbRssAvailable.asObservable();
getnbRssTotalObs(): Observable<number> {
return this._nbRssTotal.asObservable();
}
getnbRssBusyObs(): Observable<number> {
return this._nbRssBusy.asObservable();
}
get nbRssAvailable(): number {
return this._nbRssAvailable.value;
getnbJobCurrentObs(): Observable<number> {
return this._nbJobCurrent.asObservable();
}
get nbRssTotal(): number {
return this._nbRssTotal.value;
}
get nbRssBusy(): number {
return this._nbRssBusy.value;
}
get nbJobCurrent(): number {
return this._nbJobCurrent.value;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment