misc
This commit is contained in:
@@ -3,6 +3,7 @@ import { RouterModule, Routes } from '@angular/router';
|
|||||||
|
|
||||||
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
import { DashboardComponent } from './components/dashboard/dashboard.component';
|
||||||
import { SplashComponent } from './components/splash/splash.component';
|
import { SplashComponent } from './components/splash/splash.component';
|
||||||
|
import { WorkerGroupComponent } from './components/worker-group/worker-group.component';
|
||||||
import { WorkerComponent } from './components/worker/worker.component';
|
import { WorkerComponent } from './components/worker/worker.component';
|
||||||
import { AppLayoutComponent } from './layout/app.layout.component';
|
import { AppLayoutComponent } from './layout/app.layout.component';
|
||||||
|
|
||||||
@@ -22,12 +23,22 @@ const routes: Routes = [
|
|||||||
path: '',
|
path: '',
|
||||||
component: DashboardComponent,
|
component: DashboardComponent,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: ':workerName',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: '',
|
||||||
|
component: WorkerGroupComponent
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: ':workerId',
|
path: ':workerId',
|
||||||
component: WorkerComponent
|
component: WorkerComponent
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
]
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { SplashComponent } from './components/splash/splash.component';
|
|||||||
import { WorkerComponent } from './components/worker/worker.component';
|
import { WorkerComponent } from './components/worker/worker.component';
|
||||||
import { AppLayoutModule } from './layout/app.layout.module';
|
import { AppLayoutModule } from './layout/app.layout.module';
|
||||||
import { NumberSuffixPipe } from './pipes/number-suffix.pipe';
|
import { NumberSuffixPipe } from './pipes/number-suffix.pipe';
|
||||||
|
import { DateAgoPipe } from './pipes/date-ago.pipe';
|
||||||
|
import { WorkerGroupComponent } from './components/worker-group/worker-group.component';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -22,7 +24,9 @@ import { NumberSuffixPipe } from './pipes/number-suffix.pipe';
|
|||||||
SplashComponent,
|
SplashComponent,
|
||||||
DashboardComponent,
|
DashboardComponent,
|
||||||
WorkerComponent,
|
WorkerComponent,
|
||||||
NumberSuffixPipe
|
NumberSuffixPipe,
|
||||||
|
DateAgoPipe,
|
||||||
|
WorkerGroupComponent
|
||||||
],
|
],
|
||||||
imports: [
|
imports: [
|
||||||
CommonModule,
|
CommonModule,
|
||||||
|
|||||||
@@ -2,23 +2,58 @@
|
|||||||
<div class="card">
|
<div class="card">
|
||||||
|
|
||||||
|
|
||||||
<p-table [rowHover]="true" [value]="clientInfo.workers" [tableStyle]="{ 'min-width': '50rem' }">
|
<p-table [rowHover]="true" groupRowsBy="name" dataKey="name" rowGroupMode="subheader"
|
||||||
|
[value]="clientInfo.workers" [tableStyle]="{ 'min-width': '50rem' }">
|
||||||
|
|
||||||
|
|
||||||
<ng-template pTemplate="header">
|
<ng-template pTemplate="header">
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>ID</th>
|
<th>Session ID</th>
|
||||||
<th>Hash Rate</th>
|
<th>Hash Rate</th>
|
||||||
<th>Best Luck</th>
|
<th>Best Difficulty</th>
|
||||||
|
<th>Uptime</th>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
<ng-template pTemplate="body" let-worker>
|
|
||||||
<tr [routerLink]="[worker.id]">
|
|
||||||
<td>{{worker.name}}</td>
|
<ng-template pTemplate="groupheader" let-worker let-rowIndex="rowIndex" let-expanded="expanded">
|
||||||
<td>{{worker.id}}</td>
|
<tr [routerLink]="[worker.name]">
|
||||||
<td>{{worker.hashRate}} Gh/s</td>
|
<td>
|
||||||
|
<button (click)="$event.stopImmediatePropagation()" type="button" pButton pRipple
|
||||||
|
[pRowToggler]="worker" class="p-button-text p-button-rounded p-button-plain mr-2"
|
||||||
|
[icon]="expanded ? 'pi pi-chevron-down' : 'pi pi-chevron-right'"></button>
|
||||||
|
|
||||||
|
<span class="worker-name font-bold ml-2">{{worker.name}} </span>
|
||||||
|
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{getSessionCount(worker.name, clientInfo.workers)}} Sessions
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{getTotalHashRate(worker.name, clientInfo.workers)}} GH/s
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{getBestDifficulty(worker.name, clientInfo.workers) | numberSuffix}}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{{getTotalUptime(worker.name, clientInfo.workers) | dateAgo}} (cumulative)
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</ng-template>
|
||||||
|
|
||||||
|
|
||||||
|
<ng-template pTemplate="rowexpansion" let-worker>
|
||||||
|
<tr [routerLink]="[worker.name, worker.sessionId]">
|
||||||
|
<td></td>
|
||||||
|
<td>{{worker.sessionId}}</td>
|
||||||
|
<td>{{worker.hashRate}} GH/s</td>
|
||||||
<td>{{worker.bestDifficulty | numberSuffix}}</td>
|
<td>{{worker.bestDifficulty | numberSuffix}}</td>
|
||||||
|
<td>{{worker.startTime | dateAgo}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
||||||
|
|
||||||
</p-table>
|
</p-table>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.worker-name {
|
||||||
|
line-height: 42px;
|
||||||
|
}
|
||||||
@@ -20,4 +20,39 @@ export class DashboardComponent {
|
|||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public getSessionCount(name: string, workers: any[]) {
|
||||||
|
const workersByName = workers.filter(w => w.name == name);
|
||||||
|
return workersByName.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalHashRate(name: string, workers: any[]) {
|
||||||
|
const workersByName = workers.filter(w => w.name == name);
|
||||||
|
const sum = workersByName.reduce((pre, cur, idx, arr) => {
|
||||||
|
return pre += cur.hashRate;
|
||||||
|
}, 0);
|
||||||
|
return Math.floor(sum);
|
||||||
|
}
|
||||||
|
|
||||||
|
public getBestDifficulty(name: string, workers: any[]) {
|
||||||
|
const workersByName = workers.filter(w => w.name == name);
|
||||||
|
const best = workersByName.reduce((pre, cur, idx, arr) => {
|
||||||
|
if (cur.bestDifficulty > pre) {
|
||||||
|
return cur.bestDifficulty;
|
||||||
|
}
|
||||||
|
return pre;
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
public getTotalUptime(name: string, workers: any[]) {
|
||||||
|
const now = new Date().getTime();
|
||||||
|
const workersByName = workers.filter(w => w.name == name);
|
||||||
|
const sum = workersByName.reduce((pre, cur, idx, arr) => {
|
||||||
|
return pre += now - new Date(cur.startTime).getTime();
|
||||||
|
}, 0);
|
||||||
|
return new Date(now - sum);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<div class="grid">
|
||||||
|
<ng-container *ngIf="workerInfo$ | async as workerInfo">
|
||||||
|
<div class="col-12 lg:col-6 xl:col-3">
|
||||||
|
<div class="card mb-0">
|
||||||
|
<div class="flex justify-content-between mb-3">
|
||||||
|
<div>
|
||||||
|
<span class="block text-500 font-medium mb-3">ID</span>
|
||||||
|
<div class="text-900 font-medium text-xl">{{workerInfo.name}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-center bg-blue-100 border-round"
|
||||||
|
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
||||||
|
<i class="pi pi-id-card text-blue-500 text-xl"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <span class="text-green-500 font-medium">24 new </span> -->
|
||||||
|
<span class="text-500">{{workerInfo.sessionId}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 lg:col-6 xl:col-3">
|
||||||
|
<div class="card mb-0">
|
||||||
|
<div class="flex justify-content-between mb-3">
|
||||||
|
<div>
|
||||||
|
<span class="block text-500 font-medium mb-3">Best Difficulty</span>
|
||||||
|
<div class="text-900 font-medium text-xl">{{workerInfo.bestDifficulty | numberSuffix}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-center bg-orange-100 border-round"
|
||||||
|
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
||||||
|
<i class="pi pi-star text-orange-500 text-xl"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="text-green-500 font-medium">{{workerInfo.bestDifficulty | number}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-12 lg:col-6 xl:col-3">
|
||||||
|
<div class="card mb-0">
|
||||||
|
<div class="flex justify-content-between mb-3">
|
||||||
|
<div>
|
||||||
|
<span class="block text-500 font-medium mb-3">Uptime</span>
|
||||||
|
<div class="text-900 font-medium text-xl">{{workerInfo.startTime | dateAgo}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-center bg-cyan-100 border-round"
|
||||||
|
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
||||||
|
<i class="pi pi-clock text-cyan-500 text-xl"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <span class="text-green-500 font-medium">520 </span>-->
|
||||||
|
<span class="text-500">Since {{workerInfo.startTime | date : 'short'}}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="col-12 lg:col-6 xl:col-3">
|
||||||
|
<div class="card mb-0">
|
||||||
|
<div class="flex justify-content-between mb-3">
|
||||||
|
<div>
|
||||||
|
<span class="block text-500 font-medium mb-3">Comments</span>
|
||||||
|
<div class="text-900 font-medium text-xl">152 Unread</div>
|
||||||
|
</div>
|
||||||
|
<div class="flex align-items-center justify-content-center bg-purple-100 border-round"
|
||||||
|
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
||||||
|
<i class="pi pi-comment text-purple-500 text-xl"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span class="text-green-500 font-medium">85 </span>
|
||||||
|
<span class="text-500">responded</span>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</ng-container>
|
||||||
|
|
||||||
|
|
||||||
|
<div class="col-12" *ngIf="chartData$ | async as chartData">
|
||||||
|
<div class="card">
|
||||||
|
<p-chart type="line" [data]="chartData" [options]="chartOptions"></p-chart>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { WorkerGroupComponent } from './worker-group.component';
|
||||||
|
|
||||||
|
describe('WorkerGroupComponent', () => {
|
||||||
|
let component: WorkerGroupComponent;
|
||||||
|
let fixture: ComponentFixture<WorkerGroupComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
declarations: [ WorkerGroupComponent ]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(WorkerGroupComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
import { Component } from '@angular/core';
|
||||||
|
import { ActivatedRoute } from '@angular/router';
|
||||||
|
import { map, Observable, shareReplay } from 'rxjs';
|
||||||
|
|
||||||
|
import { WorkerService } from '../../services/worker.service';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'app-worker-group',
|
||||||
|
templateUrl: './worker-group.component.html',
|
||||||
|
styleUrls: ['./worker-group.component.scss']
|
||||||
|
})
|
||||||
|
export class WorkerGroupComponent {
|
||||||
|
|
||||||
|
public workerInfo$: Observable<any>;
|
||||||
|
|
||||||
|
public chartData$: Observable<any>;
|
||||||
|
|
||||||
|
public chartOptions: any;
|
||||||
|
|
||||||
|
constructor(private workerService: WorkerService, private route: ActivatedRoute) {
|
||||||
|
const documentStyle = getComputedStyle(document.documentElement);
|
||||||
|
const textColor = documentStyle.getPropertyValue('--text-color');
|
||||||
|
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
|
||||||
|
const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
|
||||||
|
|
||||||
|
this.workerInfo$ = this.workerService.getWorkerInfo(this.route.snapshot.params['address'], this.route.snapshot.params['workerName'], this.route.snapshot.params['workerId']).pipe(
|
||||||
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
|
)
|
||||||
|
|
||||||
|
this.chartData$ = this.workerInfo$.pipe(
|
||||||
|
map((workerInfo: any) => {
|
||||||
|
|
||||||
|
return {
|
||||||
|
labels: workerInfo.chartData.map((d: any) => d.label),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: workerInfo.name,
|
||||||
|
data: workerInfo.chartData.map((d: any) => d.data),
|
||||||
|
fill: false,
|
||||||
|
backgroundColor: documentStyle.getPropertyValue('--bluegray-700'),
|
||||||
|
borderColor: documentStyle.getPropertyValue('--bluegray-700'),
|
||||||
|
tension: .4
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.chartOptions = {
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
labels: {
|
||||||
|
color: textColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
x: {
|
||||||
|
type: 'time',
|
||||||
|
time: {
|
||||||
|
unit: 'minute', // Set the unit to 'minute'
|
||||||
|
stepSize: 10, // Set the desired interval between labels in minutes
|
||||||
|
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
color: textColorSecondary
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
color: surfaceBorder,
|
||||||
|
drawBorder: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
y: {
|
||||||
|
ticks: {
|
||||||
|
color: textColorSecondary,
|
||||||
|
callback: (value: number) => value + ' GH/s',
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
color: surfaceBorder,
|
||||||
|
drawBorder: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -13,14 +13,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <span class="text-green-500 font-medium">24 new </span> -->
|
<!-- <span class="text-green-500 font-medium">24 new </span> -->
|
||||||
<span class="text-500">{{workerInfo.id}}</span>
|
<span class="text-500">{{workerInfo.sessionId}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 lg:col-6 xl:col-3">
|
<div class="col-12 lg:col-6 xl:col-3">
|
||||||
<div class="card mb-0">
|
<div class="card mb-0">
|
||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Best Luck</span>
|
<span class="block text-500 font-medium mb-3">Best Difficulty</span>
|
||||||
<div class="text-900 font-medium text-xl">{{workerInfo.bestDifficulty | numberSuffix}}
|
<div class="text-900 font-medium text-xl">{{workerInfo.bestDifficulty | numberSuffix}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -32,23 +32,23 @@
|
|||||||
<span class="text-green-500 font-medium">{{workerInfo.bestDifficulty | number}}</span>
|
<span class="text-green-500 font-medium">{{workerInfo.bestDifficulty | number}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="col-12 lg:col-6 xl:col-3">
|
<div class="col-12 lg:col-6 xl:col-3">
|
||||||
<div class="card mb-0">
|
<div class="card mb-0">
|
||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
<span class="block text-500 font-medium mb-3">Customers</span>
|
<span class="block text-500 font-medium mb-3">Uptime</span>
|
||||||
<div class="text-900 font-medium text-xl">28441</div>
|
<div class="text-900 font-medium text-xl">{{workerInfo.startTime | dateAgo}}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex align-items-center justify-content-center bg-cyan-100 border-round"
|
<div class="flex align-items-center justify-content-center bg-cyan-100 border-round"
|
||||||
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
[ngStyle]="{width: '2.5rem', height: '2.5rem'}">
|
||||||
<i class="pi pi-inbox text-cyan-500 text-xl"></i>
|
<i class="pi pi-clock text-cyan-500 text-xl"></i>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<span class="text-green-500 font-medium">520 </span>
|
<!-- <span class="text-green-500 font-medium">520 </span>-->
|
||||||
<span class="text-500">newly registered</span>
|
<span class="text-500">Since {{workerInfo.startTime | date : 'short'}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12 lg:col-6 xl:col-3">
|
<!-- <div class="col-12 lg:col-6 xl:col-3">
|
||||||
<div class="card mb-0">
|
<div class="card mb-0">
|
||||||
<div class="flex justify-content-between mb-3">
|
<div class="flex justify-content-between mb-3">
|
||||||
<div>
|
<div>
|
||||||
|
|||||||
@@ -23,49 +23,19 @@ export class WorkerComponent {
|
|||||||
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
|
const textColorSecondary = documentStyle.getPropertyValue('--text-color-secondary');
|
||||||
const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
|
const surfaceBorder = documentStyle.getPropertyValue('--surface-border');
|
||||||
|
|
||||||
this.workerInfo$ = this.workerService.getWorkerInfo(this.route.snapshot.params['address'], this.route.snapshot.params['workerId']).pipe(
|
this.workerInfo$ = this.workerService.getWorkerInfo(this.route.snapshot.params['address'], this.route.snapshot.params['workerName'], this.route.snapshot.params['workerId']).pipe(
|
||||||
shareReplay({ bufferSize: 1, refCount: true })
|
shareReplay({ bufferSize: 1, refCount: true })
|
||||||
)
|
)
|
||||||
|
|
||||||
this.chartData$ = this.workerInfo$.pipe(
|
this.chartData$ = this.workerInfo$.pipe(
|
||||||
map((workerInfo: any) => {
|
map((workerInfo: any) => {
|
||||||
|
|
||||||
const GROUP_SIZE = 60;
|
|
||||||
const slice = workerInfo.hashData.length % GROUP_SIZE == 0 ? workerInfo.hashData : workerInfo.hashData.slice(0, workerInfo.hashData.length - workerInfo.hashData.length % GROUP_SIZE)
|
|
||||||
const reducedData = ((slice as any[])
|
|
||||||
.reduce((pre, cur, idx, arr) => {
|
|
||||||
if (idx % GROUP_SIZE != 0) {
|
|
||||||
pre[pre.length - 1].difficulty += cur.difficulty;
|
|
||||||
} else {
|
|
||||||
pre.push(cur);
|
|
||||||
}
|
|
||||||
return pre;
|
|
||||||
}, []) as any[]);
|
|
||||||
|
|
||||||
const labels = reducedData.reduce((pre, cur, idx, arr) => {
|
|
||||||
if (idx == 0) {
|
|
||||||
return pre;
|
|
||||||
}
|
|
||||||
pre.push(new Date(cur.time));
|
|
||||||
return pre;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const data = reducedData
|
|
||||||
.reduce((pre, cur, idx, arr) => {
|
|
||||||
if (idx == 0) {
|
|
||||||
return pre;
|
|
||||||
}
|
|
||||||
//hashrate = (nonce_difficulty * 2^32) / time_to_find
|
|
||||||
pre.push((cur.difficulty * 4294967296 / (new Date(cur.time).getTime() - new Date(arr[idx - 1].time).getTime())) / 1000000);
|
|
||||||
return pre;
|
|
||||||
|
|
||||||
}, []);
|
|
||||||
return {
|
return {
|
||||||
labels,
|
labels: workerInfo.chartData.map((d: any) => d.label),
|
||||||
datasets: [
|
datasets: [
|
||||||
{
|
{
|
||||||
label: workerInfo.name,
|
label: workerInfo.name,
|
||||||
data,
|
data: workerInfo.chartData.map((d: any) => d.data),
|
||||||
fill: false,
|
fill: false,
|
||||||
backgroundColor: documentStyle.getPropertyValue('--bluegray-700'),
|
backgroundColor: documentStyle.getPropertyValue('--bluegray-700'),
|
||||||
borderColor: documentStyle.getPropertyValue('--bluegray-700'),
|
borderColor: documentStyle.getPropertyValue('--bluegray-700'),
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import { DateAgoPipe } from './date-ago.pipe';
|
||||||
|
|
||||||
|
describe('DateAgoPipe', () => {
|
||||||
|
it('create an instance', () => {
|
||||||
|
const pipe = new DateAgoPipe();
|
||||||
|
expect(pipe).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
import { Pipe, PipeTransform } from '@angular/core';
|
||||||
|
|
||||||
|
@Pipe({
|
||||||
|
name: 'dateAgo',
|
||||||
|
pure: true
|
||||||
|
})
|
||||||
|
export class DateAgoPipe implements PipeTransform {
|
||||||
|
|
||||||
|
transform(value: any, args?: any): any {
|
||||||
|
if (value) {
|
||||||
|
const seconds = Math.floor((+new Date() - +new Date(value)) / 1000);
|
||||||
|
if (seconds < 29) // less than 30 seconds ago will show as 'Just now'
|
||||||
|
return 'Just now';
|
||||||
|
const intervals: { [key: string]: number } = {
|
||||||
|
'year': 31536000,
|
||||||
|
'month': 2592000,
|
||||||
|
'week': 604800,
|
||||||
|
'day': 86400,
|
||||||
|
'hour': 3600,
|
||||||
|
'minute': 60,
|
||||||
|
'second': 1
|
||||||
|
};
|
||||||
|
let counter;
|
||||||
|
for (const i in intervals) {
|
||||||
|
counter = Math.floor(seconds / intervals[i]);
|
||||||
|
if (counter > 0)
|
||||||
|
if (counter === 1) {
|
||||||
|
return counter + ' ' + i + ''; // singular (1 day ago)
|
||||||
|
} else {
|
||||||
|
return counter + ' ' + i + 's'; // plural (2 days ago)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -14,7 +14,7 @@ export class WorkerService {
|
|||||||
private httpClient: HttpClient
|
private httpClient: HttpClient
|
||||||
) { }
|
) { }
|
||||||
|
|
||||||
public getWorkerInfo(address: string, workerId: string): Observable<any> {
|
public getWorkerInfo(address: string, workerName: string, workerId: string): Observable<any> {
|
||||||
return this.httpClient.get(`${environment.API_URL}/api/client/${address}/${workerId}`);
|
return this.httpClient.get(`${environment.API_URL}/api/client/${address}/${workerName}/${workerId}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user