Merge pull request #14066 from grafana/panel-size-refactor
Panel size refactor
This commit is contained in:
@@ -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>
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// 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;
|
||||
}
|
||||
|
||||
+10
-15
@@ -1,7 +1,6 @@
|
||||
// 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"
|
||||
|
||||
Reference in New Issue
Block a user