Commit 604add07 by Torkel Ödegaard Committed by GitHub

Merge pull request #14066 from grafana/panel-size-refactor

Panel size refactor
parents 6d65432c 90c41bb0
......@@ -163,6 +163,7 @@
"react-sizeme": "^2.3.6",
"react-table": "^6.8.6",
"react-transition-group": "^2.2.1",
"react-virtualized": "^9.21.0",
"redux": "^4.0.0",
"redux-logger": "^3.0.6",
"redux-thunk": "^2.3.0",
......
......@@ -26,6 +26,7 @@ export class Switch extends PureComponent<Props, State> {
render() {
const { labelClass = '', switchClass = '', label, checked, small } = this.props;
const labelId = `check-${this.state.id}`;
let labelClassName = `gf-form-label ${labelClass} pointer`;
let switchClassName = `gf-form-switch ${switchClass}`;
......
......@@ -176,6 +176,7 @@ export class DashboardGrid extends React.Component<DashboardGridProps, any> {
renderPanels() {
const panelElements = [];
console.log('render panels');
for (const panel of this.props.dashboard.panels) {
const panelClasses = classNames({ panel: true, 'panel--fullscreen': panel.fullscreen });
......
......@@ -4,6 +4,9 @@ import React, { Component } from 'react';
// Services
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
// Utils
import kbn from 'app/core/utils/kbn';
// Types
import { TimeRange, LoadingState, DataQueryOptions, DataQueryResponse, TimeSeries } from 'app/types';
......@@ -19,7 +22,10 @@ export interface Props {
dashboardId?: number;
isVisible?: boolean;
timeRange?: TimeRange;
widthPixels: number;
refreshCounter: number;
minInterval?: string;
maxDataPoints?: number;
children: (r: RenderProps) => JSX.Element;
}
......@@ -30,6 +36,8 @@ export interface State {
}
export class DataPanel extends Component<Props, State> {
dataSourceSrv = getDatasourceSrv();
static defaultProps = {
isVisible: true,
panelId: 1,
......@@ -49,7 +57,7 @@ export class DataPanel extends Component<Props, State> {
}
componentDidMount() {
console.log('DataPanel mount');
this.issueQueries();
}
async componentDidUpdate(prevProps: Props) {
......@@ -61,11 +69,11 @@ export class DataPanel extends Component<Props, State> {
}
hasPropsChanged(prevProps: Props) {
return this.props.refreshCounter !== prevProps.refreshCounter || this.props.isVisible !== prevProps.isVisible;
return this.props.refreshCounter !== prevProps.refreshCounter;
}
issueQueries = async () => {
const { isVisible, queries, datasource, panelId, dashboardId, timeRange } = this.props;
const { isVisible, queries, datasource, panelId, dashboardId, timeRange, widthPixels, maxDataPoints } = this.props;
if (!isVisible) {
return;
......@@ -79,18 +87,22 @@ export class DataPanel extends Component<Props, State> {
this.setState({ loading: LoadingState.Loading });
try {
const dataSourceSrv = getDatasourceSrv();
const ds = await dataSourceSrv.get(datasource);
const ds = await this.dataSourceSrv.get(datasource);
// TODO interpolate variables
const minInterval = this.props.minInterval || ds.interval;
const intervalRes = kbn.calculateInterval(timeRange, widthPixels, minInterval);
const queryOptions: DataQueryOptions = {
timezone: 'browser',
panelId: panelId,
dashboardId: dashboardId,
range: timeRange,
rangeRaw: timeRange.raw,
interval: '1s',
intervalMs: 60000,
interval: intervalRes.interval,
intervalMs: intervalRes.intervalMs,
targets: queries,
maxDataPoints: 500,
maxDataPoints: maxDataPoints || widthPixels,
scopedVars: {},
cacheTimeout: null,
};
......@@ -111,17 +123,10 @@ export class DataPanel extends Component<Props, State> {
};
render() {
const { response, loading, isFirstLoad } = this.state;
console.log('data panel render');
const { response, loading } = this.state;
const timeSeries = response.data;
if (isFirstLoad && (loading === LoadingState.Loading || loading === LoadingState.NotStarted)) {
return (
<div className="loading">
<p>Loading</p>
</div>
);
}
console.log('data panel render');
return (
<>
......@@ -139,7 +144,7 @@ export class DataPanel extends Component<Props, State> {
if (loading === LoadingState.Loading) {
return (
<div className="panel__loading">
<div className="panel-loading">
<i className="fa fa-spinner fa-spin" />
</div>
);
......
// Libraries
import React, { ComponentClass, PureComponent } from 'react';
import { AutoSizer } from 'react-virtualized';
// Services
import { getTimeSrv, TimeSrv } from '../time_srv';
......@@ -87,31 +88,45 @@ export class PanelChrome extends PureComponent<Props, State> {
console.log('panelChrome render');
return (
<div className="panel-container">
<PanelHeader panel={panel} dashboard={dashboard} timeInfo={timeInfo} />
<div className="panel-content">
<DataPanel
datasource={datasource}
queries={targets}
timeRange={timeRange}
isVisible={this.isVisible}
refreshCounter={refreshCounter}
>
{({ loading, timeSeries }) => {
console.log('panelcrome inner render');
return (
<PanelComponent
loading={loading}
timeSeries={timeSeries}
timeRange={timeRange}
options={panel.getOptions()}
renderCounter={renderCounter}
/>
);
}}
</DataPanel>
</div>
</div>
<AutoSizer>
{({ width, height }) => {
if (width === 0) {
return null;
}
return (
<div className="panel-container panel-container--absolute">
<DataPanel
datasource={datasource}
queries={targets}
timeRange={timeRange}
isVisible={this.isVisible}
widthPixels={width}
refreshCounter={refreshCounter}
>
{({ loading, timeSeries }) => {
return (
<>
<PanelHeader panel={panel} dashboard={dashboard} timeInfo={timeInfo} />
<div className="panel-content">
<PanelComponent
loading={loading}
timeSeries={timeSeries}
timeRange={timeRange}
options={panel.getOptions()}
width={width}
height={height}
renderCounter={renderCounter}
/>
</div>
</>
);
}}
</DataPanel>
</div>
);
}}
</AutoSizer>
);
}
}
......@@ -23,7 +23,7 @@ export class Graph2 extends PureComponent<Props> {
}
render() {
const { timeSeries, timeRange } = this.props;
const { timeSeries, timeRange, width, height } = this.props;
const { showLines, showBars, showPoints } = this.props.options;
const vmSeries = getTimeSeriesVMs({
......@@ -38,6 +38,8 @@ export class Graph2 extends PureComponent<Props> {
showLines={showLines}
showPoints={showPoints}
showBars={showBars}
width={width}
height={height}
/>
);
}
......
......@@ -6,6 +6,8 @@ export interface PanelProps<T = any> {
loading: LoadingState;
options: T;
renderCounter: number;
width: number;
height: number;
}
export interface PanelOptionsProps<T = any> {
......
......@@ -89,4 +89,6 @@ export interface DataQueryOptions {
export interface DataSourceApi {
query(options: DataQueryOptions): Promise<DataQueryResponse>;
testDatasource(): Promise<any>;
interval?: string;
}
// Libraries
import $ from 'jquery';
import React, { PureComponent } from 'react';
import { withSize } from 'react-sizeme';
import 'vendor/flot/jquery.flot';
import 'vendor/flot/jquery.flot.time';
......@@ -14,7 +13,8 @@ interface GraphProps {
showLines?: boolean;
showPoints?: boolean;
showBars?: boolean;
size?: { width: number; height: number };
width: number;
height: number;
}
export class Graph extends PureComponent<GraphProps> {
......@@ -24,16 +24,10 @@ export class Graph extends PureComponent<GraphProps> {
showBars: false,
};
element: any;
element: HTMLElement;
componentDidUpdate(prevProps: GraphProps) {
if (
prevProps.timeSeries !== this.props.timeSeries ||
prevProps.timeRange !== this.props.timeRange ||
prevProps.size !== this.props.size
) {
this.draw();
}
componentDidUpdate() {
this.draw();
}
componentDidMount() {
......@@ -41,13 +35,13 @@ export class Graph extends PureComponent<GraphProps> {
}
draw() {
const { size, timeSeries, timeRange, showLines, showBars, showPoints } = this.props;
const { width, timeSeries, timeRange, showLines, showBars, showPoints } = this.props;
if (!size) {
if (!width) {
return;
}
const ticks = (size.width || 0) / 100;
const ticks = width / 100;
const min = timeRange.from.valueOf();
const max = timeRange.to.valueOf();
......@@ -98,6 +92,7 @@ export class Graph extends PureComponent<GraphProps> {
};
try {
console.log('Graph render');
$.plot(this.element, timeSeries, flotOptions);
} catch (err) {
console.log('Graph rendering error', err, flotOptions, timeSeries);
......@@ -139,4 +134,4 @@ function time_format(ticks, min, max) {
return '%H:%M';
}
export default withSize()(Graph);
export default Graph;
......@@ -43,6 +43,7 @@ div.flot-text {
position: relative;
border-radius: 3px;
height: 100%;
width: 100%;
&.panel-transparent {
background-color: transparent;
......@@ -60,6 +61,10 @@ div.flot-text {
&--is-editing {
height: auto;
}
&--absolute {
position: absolute;
}
}
.panel-content {
......
......@@ -25,6 +25,13 @@
esutils "^2.0.2"
js-tokens "^4.0.0"
"@babel/runtime@^7.1.2":
version "7.1.5"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.1.5.tgz#4170907641cf1f61508f563ece3725150cc6fe39"
integrity sha512-xKnPpXG/pvK1B90JkwwxSGii90rQGKtzcMt2gI5G6+M0REXaq6rOHsGC2ay6/d0Uje7zzvSzjEzfR3ENhFlrfA==
dependencies:
regenerator-runtime "^0.12.0"
"@babel/types@^7.0.0":
version "7.1.2"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.1.2.tgz#183e7952cf6691628afdc2e2b90d03240bac80c0"
......@@ -2624,7 +2631,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
classnames@2.x, classnames@^2.2.5, classnames@^2.2.6:
classnames@2.x, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6:
version "2.2.6"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.2.6.tgz#43935bffdd291f326dad0a205309b38d00f650ce"
integrity sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==
......@@ -4163,6 +4170,13 @@ dom-css@^2.0.0:
prefix-style "2.0.1"
to-camel-case "1.0.0"
"dom-helpers@^2.4.0 || ^3.0.0":
version "3.4.0"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.4.0.tgz#e9b369700f959f62ecde5a6babde4bccd9169af8"
integrity sha512-LnuPJ+dwqKDIyotW1VzmOZ5TONUN7CwkCR5hrgawTUbkBGYdeoNLZo6nNfGkCrjtE1nXXaj7iMMpDa8/d9WoIA==
dependencies:
"@babel/runtime" "^7.1.2"
dom-helpers@^3.3.1:
version "3.3.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-3.3.1.tgz#fc1a4e15ffdf60ddde03a480a9c0fece821dd4a6"
......@@ -8431,7 +8445,7 @@ longest@^1.0.1:
resolved "https://registry.yarnpkg.com/longest/-/longest-1.0.1.tgz#30a0b2da38f73770e8294a0d22e6625ed77d0097"
integrity sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc=
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
loose-envify@^1.0.0, loose-envify@^1.1.0, loose-envify@^1.3.0, loose-envify@^1.3.1, loose-envify@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/loose-envify/-/loose-envify-1.4.0.tgz#71ee51fa7be4caec1a63839f7e682d8132d30caf"
integrity sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==
......@@ -11413,6 +11427,18 @@ react-transition-group@^2.2.1:
prop-types "^15.6.2"
react-lifecycles-compat "^3.0.4"
react-virtualized@^9.21.0:
version "9.21.0"
resolved "https://registry.yarnpkg.com/react-virtualized/-/react-virtualized-9.21.0.tgz#8267c40ffb48db35b242a36dea85edcf280a6506"
integrity sha512-duKD2HvO33mqld4EtQKm9H9H0p+xce1c++2D5xn59Ma7P8VT7CprfAe5hwjd1OGkyhqzOZiTMlTal7LxjH5yBQ==
dependencies:
babel-runtime "^6.26.0"
classnames "^2.2.3"
dom-helpers "^2.4.0 || ^3.0.0"
loose-envify "^1.3.0"
prop-types "^15.6.0"
react-lifecycles-compat "^3.0.4"
react@^16.5.0:
version "16.5.2"
resolved "https://registry.yarnpkg.com/react/-/react-16.5.2.tgz#19f6b444ed139baa45609eee6dc3d318b3895d42"
......@@ -11686,6 +11712,11 @@ regenerator-runtime@^0.11.0:
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz#be05ad7f9bf7d22e056f9726cee5017fbf19e2e9"
integrity sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==
regenerator-runtime@^0.12.0:
version "0.12.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.12.1.tgz#fa1a71544764c036f8c49b13a08b2594c9f8a0de"
integrity sha512-odxIc1/vDlo4iZcfXqRYFj0vpXFNoGdKMAUieAlFYO6m/nl5e9KR/beGf41z4a1FI+aQgtjhuaSlDxQ0hmkrHg==
regenerator-transform@^0.10.0:
version "0.10.1"
resolved "https://registry.yarnpkg.com/regenerator-transform/-/regenerator-transform-0.10.1.tgz#1e4996837231da8b7f3cf4114d71b5691a0680dd"
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment