New Panel Edit: works for panels with and without queries (#22024)

* Make new edit work again

* add cx

Co-authored-by: Ryan McKinley <ryantxu@gmail.com>
This commit is contained in:
Dominik Prokop 2020-02-08 13:23:16 +01:00 committed by GitHub
parent a51ac787c0
commit e17b76ad7a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 74 additions and 16 deletions

View File

@ -1,6 +1,6 @@
import React, { PureComponent } from 'react'; import React, { PureComponent } from 'react';
import { css, cx } from 'emotion'; import { css, cx } from 'emotion';
import { GrafanaTheme } from '@grafana/data'; import { GrafanaTheme, PanelData, LoadingState, DefaultTimeRange, PanelEvents } from '@grafana/data';
import { stylesFactory, Forms } from '@grafana/ui'; import { stylesFactory, Forms } from '@grafana/ui';
import config from 'app/core/config'; import config from 'app/core/config';
@ -12,6 +12,7 @@ import SplitPane from 'react-split-pane';
import { StoreState } from '../../../../types/store'; import { StoreState } from '../../../../types/store';
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { updateLocation } from '../../../../core/reducers/location'; import { updateLocation } from '../../../../core/reducers/location';
import { Unsubscribable } from 'rxjs';
const getStyles = stylesFactory((theme: GrafanaTheme) => { const getStyles = stylesFactory((theme: GrafanaTheme) => {
const resizer = css` const resizer = css`
@ -61,15 +62,63 @@ interface Props {
} }
interface State { interface State {
pluginLoadedCounter: number;
dirtyPanel?: PanelModel; dirtyPanel?: PanelModel;
data: PanelData;
} }
export class PanelEditor extends PureComponent<Props, State> { export class PanelEditor extends PureComponent<Props, State> {
querySubscription: Unsubscribable;
state: State = {
pluginLoadedCounter: 0,
data: {
state: LoadingState.NotStarted,
series: [],
timeRange: DefaultTimeRange,
},
};
constructor(props: Props) { constructor(props: Props) {
super(props); super(props);
const { panel } = props;
// To ensure visualisation settings are re-rendered when plugin has loaded
// panelInitialised event is emmited from PanelChrome
props.panel.events.on(PanelEvents.panelInitialized, () => {
this.setState(state => ({
pluginLoadedCounter: state.pluginLoadedCounter + 1,
}));
});
}
componentDidMount() {
const { panel } = this.props;
const dirtyPanel = panel.getEditClone(); const dirtyPanel = panel.getEditClone();
this.state = { dirtyPanel }; this.setState({ dirtyPanel });
// Get data from any pending
panel
.getQueryRunner()
.getData()
.subscribe({
next: (data: PanelData) => {
this.setState({ data });
// TODO, cancel????
},
});
// Listen for queries on the new panel
const queryRunner = dirtyPanel.getQueryRunner();
this.querySubscription = queryRunner.getData().subscribe({
next: (data: PanelData) => this.setState({ data }),
});
}
componentWillUnmount() {
if (this.querySubscription) {
this.querySubscription.unsubscribe();
}
//this.cleanUpAngularOptions();
} }
onPanelUpdate = () => { onPanelUpdate = () => {

View File

@ -85,16 +85,21 @@ export class PanelChrome extends PureComponent<Props, State> {
}, },
isFirstLoad: false, isFirstLoad: false,
}); });
} else if (isInEditMode && this.panelHasLastResult()) { } else {
console.log('Reusing results!'); if (isInEditMode) {
const lastResult = panel.getQueryRunner().getLastResult(); this.querySubscription = panel
if (lastResult) { .getQueryRunner()
this.onDataUpdate(lastResult); .getData()
.subscribe({
next: data => this.onDataUpdate(data),
});
} }
} else if (!this.wantsQueryExecution) {
if (!this.wantsQueryExecution) {
this.setState({ isFirstLoad: false }); this.setState({ isFirstLoad: false });
} }
} }
}
componentWillUnmount() { componentWillUnmount() {
this.props.panel.events.off(PanelEvents.refresh, this.onRefresh); this.props.panel.events.off(PanelEvents.refresh, this.onRefresh);
@ -244,11 +249,7 @@ export class PanelChrome extends PureComponent<Props, State> {
}; };
get wantsQueryExecution() { get wantsQueryExecution() {
return !( return !(this.props.plugin.meta.skipDataQuery || this.hasPanelSnapshot);
this.props.plugin.meta.skipDataQuery ||
this.hasPanelSnapshot ||
(this.props.isInEditMode && !this.panelHasLastResult())
);
} }
onChangeTimeRange = (timeRange: AbsoluteTimeRange) => { onChangeTimeRange = (timeRange: AbsoluteTimeRange) => {

View File

@ -18,6 +18,7 @@ import config from 'app/core/config';
import { PanelQueryRunner } from './PanelQueryRunner'; import { PanelQueryRunner } from './PanelQueryRunner';
import { eventFactory } from '@grafana/data'; import { eventFactory } from '@grafana/data';
import { take } from 'rxjs/operators';
export const panelAdded = eventFactory<PanelModel | undefined>('panel-added'); export const panelAdded = eventFactory<PanelModel | undefined>('panel-added');
export const panelRemoved = eventFactory<PanelModel | undefined>('panel-removed'); export const panelRemoved = eventFactory<PanelModel | undefined>('panel-removed');
@ -349,7 +350,14 @@ export class PanelModel {
getEditClone() { getEditClone() {
const clone = new PanelModel(this.getSaveModel()); const clone = new PanelModel(this.getSaveModel());
clone.queryRunner = new PanelQueryRunner(this.queryRunner.getLastResult()); clone.queryRunner = new PanelQueryRunner();
// This will send the last result to the new runner
this.getQueryRunner()
.getData()
.pipe(take(1))
.subscribe(val => clone.queryRunner.pipeDataToSubject(val));
clone.isNewEdit = true; clone.isNewEdit = true;
return clone; return clone;
} }