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