Resize detector, start building legend, axis font colors

Signed-off-by: Julius Volz <julius.volz@gmail.com>
This commit is contained in:
Julius Volz 2019-02-15 16:30:54 +01:00
parent d79ef2b7f7
commit 8e75eb5dfb
6 changed files with 86 additions and 49 deletions

29
package-lock.json generated
View file

@ -996,6 +996,14 @@
"@types/react": "*"
}
},
"@types/react-resize-detector": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@types/react-resize-detector/-/react-resize-detector-3.1.0.tgz",
"integrity": "sha512-q/kuav2WHLqCOypvNMWR7S3UKSphE0urlvgkiaKpnGXOPsy6/3BCrr+HzcoaMOvuZW7bFngbheS2gITRl4B1xQ==",
"requires": {
"@types/react": "*"
}
},
"@types/reactstrap": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/@types/reactstrap/-/reactstrap-7.1.3.tgz",
@ -8917,6 +8925,11 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
},
"lodash-es": {
"version": "4.17.11",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.11.tgz",
"integrity": "sha512-DHb1ub+rMjjrxqlB3H56/6MXtm1lSksDp2rA2cNWjG8mlDUYFhUj3Di2Zn5IwSU87xLv8tNIQ7sSwE/YOX/D/Q=="
},
"lodash._reinterpolate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
@ -16969,6 +16982,17 @@
"prop-types": "^15.6.1"
}
},
"react-resize-detector": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-3.4.0.tgz",
"integrity": "sha512-T96I8Iqa1hGWyooeFA2Sl6FdPoMhXWINfEKg2/EJLxhP37+/94VNuyuyz9CRqpmApD83IWRR+lbB3r0ADMoKJg==",
"requires": {
"lodash": "^4.17.11",
"lodash-es": "^4.17.11",
"prop-types": "^15.6.2",
"resize-observer-polyfill": "^1.5.1"
}
},
"react-scripts": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/react-scripts/-/react-scripts-2.1.3.tgz",
@ -17678,6 +17702,11 @@
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
"integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8="
},
"resize-observer-polyfill": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
"integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
},
"resolve": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz",

View file

@ -11,6 +11,7 @@
"@types/node": "^11.9.3",
"@types/react": "^16.8.2",
"@types/react-dom": "^16.8.0",
"@types/react-resize-detector": "^3.1.0",
"bootstrap": "^4.2.1",
"downshift": "^3.2.2",
"flot": "^2.1.6",
@ -24,6 +25,7 @@
"npm": "^6.7.0",
"react": "^16.7.0",
"react-dom": "^16.7.0",
"react-resize-detector": "^3.4.0",
"react-scripts": "2.1.3",
"reactstrap": "^7.1.0",
"tempusdominus-bootstrap-4": "^5.1.2",

View file

@ -2,6 +2,10 @@ body {
padding-top: 10px; /* TODO remove */
}
.panel {
margin-bottom: 20px;
}
.expression-input {
margin-bottom: 10px;
}
@ -113,6 +117,13 @@ div.endtime-input {
.graph-legend {
margin: 15px 0 15px 25px;
font-size: 0.8em;
}
.graph-legend .legend-swatch {
width: 10px;
height: 10px;
background-color: red;
}
.graph {
@ -122,6 +133,10 @@ div.endtime-input {
.graph-chart {
height: 500px;
width: 100%;
/* This is picked up by Flot's axis label font renderer,
which ignores "color" and uses "fill" instead. */
fill: #495057;
font-size: 0.8em;
}
.graph-chart .flot-overlay {
@ -151,5 +166,6 @@ div.endtime-input {
}
.add-panel-btn {
margin-top: -20px;
margin-bottom: 20px;
}

View file

@ -1,5 +1,6 @@
import $ from 'jquery';
import React, { PureComponent } from 'react';
import ReactResizeDetector from 'react-resize-detector';
import { Alert } from 'reactstrap';
@ -7,10 +8,10 @@ require('flot');
require('flot/source/jquery.flot.crosshair');
require('flot/source/jquery.flot.legend');
require('flot/source/jquery.flot.time');
require('flot/source/jquery.flot.hover');
require('flot/source/jquery.flot.resize');
require('flot/source/jquery.canvaswrapper');
require('jquery.flot.tooltip');
import Legend from './Legend';
import metricToSeriesName from './MetricFomat';
var graphID = 0;
@ -32,7 +33,6 @@ interface GraphProps {
class Graph extends PureComponent<GraphProps> {
private id: number = getGraphID();
private chartRef = React.createRef<HTMLDivElement>();
private legendRef = React.createRef<HTMLDivElement>();
escapeHTML(str: string) {
var entityMap: {[key: string]: string} = {
@ -112,9 +112,7 @@ class Graph extends PureComponent<GraphProps> {
mouseActiveRadius: 100,
},
legend: {
//show: true,
labelFormatter: (s: string) => {return '&nbsp;&nbsp;' + s},
container: this.legendRef.current!,
show: false,
},
xaxis: {
mode: 'time',
@ -201,12 +199,11 @@ class Graph extends PureComponent<GraphProps> {
}
plot() {
this.destroyPlot();
if (this.chartRef.current === null || this.legendRef.current === null) {
if (this.chartRef.current === null) {
return;
}
this.destroyPlot();
$.plot($(this.chartRef.current!), this.getData(), this.getOptions());
//window.addEventListener('resize', () => this.plot());
}
destroyPlot() {
@ -231,8 +228,9 @@ class Graph extends PureComponent<GraphProps> {
return (
<div className="graph">
<ReactResizeDetector handleWidth onResize={() => this.plot()} />
<div className="graph-chart" ref={this.chartRef} />
<div className="graph-legend" ref={this.legendRef} />
<Legend series={this.getData()}/>
</div>
);
}

28
src/Legend.tsx Normal file
View file

@ -0,0 +1,28 @@
import React, { PureComponent } from 'react';
import metricToSeriesName from './MetricFomat';
interface LegendProps {
series: any; // TODO: Type this.
}
class Legend extends PureComponent<LegendProps> {
renderLegendItem(s: any) {
return (
<div key={s.label} className="legend-item">
<span className="legend-swatch">.</span>
<span className="legend-label">{s.label}</span>
</div>
);
}
render() {
return (
<div className="graph-legend">
{this.props.series.map((s: any) => {return this.renderLegendItem(s)})}
</div>
);
}
}
export default Legend;

View file

@ -187,49 +187,13 @@ class Panel extends Component<PanelProps, PanelState> {
}
}
// getEndDate = () => {
// var self = this;
// if (!self.endDate || !self.endDate.val()) {
// return moment();
// }
// return self.endDate.data('DateTimePicker').date();
// };
// getOrSetEndDate = () => {
// var self = this;
// var date = self.getEndDate();
// self.setEndDate(date);
// return date;
// };
// setEndDate = (date) => {
// var self = this;
// self.endDate.data('DateTimePicker').date(date);
// };
// increaseEnd = () => {
// var self = this;
// var newDate = moment(self.getOrSetEndDate());
// newDate.add(self.parseDuration(self.rangeInput.val()) / 2, 'seconds');
// self.setEndDate(newDate);
// self.submitQuery();
// };
// decreaseEnd = () => {
// var self = this;
// var newDate = moment(self.getOrSetEndDate());
// newDate.subtract(self.parseDuration(self.rangeInput.val()) / 2, 'seconds');
// self.setEndDate(newDate);
// self.submitQuery();
// };
handleChangeStacking = (stacked: boolean) => {
this.setState({stacked: stacked});
}
render() {
return (
<>
<div className="panel">
<Row>
<Col>
<ExpressionInput
@ -300,10 +264,10 @@ class Panel extends Component<PanelProps, PanelState> {
</Row>
<Row>
<Col>
<Button className="float-right" color="link" onClick={this.props.removePanel}>Remove Panel</Button>
<Button className="float-right" color="link" onClick={this.props.removePanel} size="sm">Remove Panel</Button>
</Col>
</Row>
</>
</div>
);
}
}