Better Sparklines (#72)

* Cleaner renders
* Add timestamps to Sparklines
* Keep track of chart history up to 1h in the past
This commit is contained in:
Maciej Hirsz
2018-10-01 11:41:40 +02:00
committed by GitHub
parent 58e19a7c58
commit 76e9155823
8 changed files with 110 additions and 37 deletions
+24 -10
View File
@@ -1,6 +1,6 @@
import * as React from 'react';
import Identicon from 'polkadot-identicon';
import { Types } from '@dotstats/common';
import { Types, Maybe, timestamp } from '@dotstats/common';
import { formatNumber, milliOrSecond, secondsWithPrecision } from '../../utils';
import { State as AppState, Node } from '../../state';
import { PersistentSet } from '../../persist';
@@ -55,23 +55,37 @@ function Truncate(props: { text: string, position?: 'left' | 'right' | 'center'
);
}
function formatMemory(kbs: number): string {
function formatStamp(stamp: Types.Timestamp): string {
const passed = (timestamp() - stamp) / 1000 | 0;
const hours = Math.round(passed / 3600);
const minutes = Math.round((passed % 3600) / 60);
const seconds = (passed % 60) | 0;
return hours ? `${hours}h ago`
: minutes ? `${minutes}m ago`
: `${seconds}s ago`;
}
function formatMemory(kbs: number, stamp: Maybe<Types.Timestamp>): string {
const ago = stamp ? ` (${formatStamp(stamp)})` : '';
const mbs = kbs / 1024 | 0;
if (mbs >= 1000) {
return `${(mbs / 1024).toFixed(1)} GB`;
return `${(mbs / 1024).toFixed(1)} GB${ago}`;
} else {
return `${mbs} MB`;
return `${mbs} MB${ago}`;
}
}
function formatCPU(cpu: number): string {
function formatCPU(cpu: number, stamp: Maybe<Types.Timestamp>): string {
const ago = stamp ? ` (${formatStamp(stamp)})` : '';
const fractionDigits = cpu > 100 ? 0
: cpu > 10 ? 1
: cpu > 1 ? 2
: 3;
return `${cpu.toFixed(fractionDigits)}%`;
return `${cpu.toFixed(fractionDigits)}%${ago}`;
}
export default class Row extends React.Component<RowProps, {}> {
@@ -134,13 +148,13 @@ export default class Row extends React.Component<RowProps, {}> {
icon: cpuIcon,
width: 40,
setting: 'cpu',
render: ({ cpu }) => {
render: ({ cpu, chartstamps }) => {
if (cpu.length < 3) {
return '-';
}
return (
<Sparkline width={48} height={16} stroke={1} format={formatCPU} values={cpu} minScale={100} />
<Sparkline width={44} height={16} stroke={1} format={formatCPU} values={cpu} stamps={chartstamps} minScale={100} />
);
}
},
@@ -149,13 +163,13 @@ export default class Row extends React.Component<RowProps, {}> {
icon: memoryIcon,
width: 40,
setting: 'mem',
render: ({ mem }) => {
render: ({ mem, chartstamps }) => {
if (mem.length < 3) {
return '-';
}
return (
<Sparkline width={48} height={16} stroke={1} format={formatMemory} values={mem} />
<Sparkline width={44} height={16} stroke={1} format={formatMemory} values={mem} stamps={chartstamps} />
);
}
},
@@ -2,5 +2,5 @@
fill: currentcolor; /* rgba(255,255,255,0.5); */
fill-opacity: 0.5;
stroke: currentcolor;
margin: 0 -14px 0 -4px;
margin: 0 -1px -3px -1px;
}
@@ -1,4 +1,5 @@
import * as React from 'react';
import { Types, Maybe } from "@dotstats/common";
import sparkline from "@fnando/sparkline";
import { Tooltip } from './';
@@ -10,8 +11,9 @@ export namespace Sparkline {
width: number;
height: number;
values: number[];
stamps?: Types.Timestamp[];
minScale?: number;
format?: (value: number) => string;
format?: (value: number, stamp: Maybe<Types.Timestamp>) => string;
}
}
@@ -21,6 +23,8 @@ export class Sparkline extends React.Component<Sparkline.Props, {}> {
public componentDidMount() {
sparkline(this.el, this.props.values, {
spotRadius: 0.1,
minScale: this.props.minScale,
interactive: true,
onmousemove: this.onMouseMove,
});
@@ -35,6 +39,7 @@ export class Sparkline extends React.Component<Sparkline.Props, {}> {
if (this.props.values !== nextProps.values) {
sparkline(this.el, nextProps.values, {
spotRadius: 0.1,
minScale,
interactive: true,
onmousemove: this.onMouseMove,
@@ -62,9 +67,9 @@ export class Sparkline extends React.Component<Sparkline.Props, {}> {
this.update = update;
}
private onMouseMove = (event: MouseEvent, data: { value: number }) => {
const { format } = this.props;
const str = format ? format(data.value) : `${data.value}`;
private onMouseMove = (event: MouseEvent, data: { value: number, index: number }) => {
const { format, stamps } = this.props;
const str = format ? format(data.value, stamps ? stamps[data.index] : null) : `${data.value}`;
this.update(str);
}
}