mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PanelContext: Add functionality to update data from panel (#66993)
This commit is contained in:
parent
6ca7d8fa37
commit
de18ed6659
@ -8,6 +8,7 @@ import {
|
|||||||
ThresholdsConfig,
|
ThresholdsConfig,
|
||||||
SplitOpen,
|
SplitOpen,
|
||||||
CoreApp,
|
CoreApp,
|
||||||
|
DataFrame,
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
|
|
||||||
import { AdHocFilterItem } from '../Table/types';
|
import { AdHocFilterItem } from '../Table/types';
|
||||||
@ -82,6 +83,12 @@ export interface PanelContext {
|
|||||||
* Called when a panel is changing the sort order of the legends.
|
* Called when a panel is changing the sort order of the legends.
|
||||||
*/
|
*/
|
||||||
onToggleLegendSort?: (sortBy: string) => void;
|
onToggleLegendSort?: (sortBy: string) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Optional, only some contexts support this. This action can be cancelled by user which will result
|
||||||
|
* in a the Promise resolving to a false value.
|
||||||
|
*/
|
||||||
|
onUpdateData?: (frames: DataFrame[]) => Promise<boolean>;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const PanelContextRoot = React.createContext<PanelContext>({
|
export const PanelContextRoot = React.createContext<PanelContext>({
|
||||||
|
@ -8,6 +8,7 @@ import {
|
|||||||
AnnotationEventUIModel,
|
AnnotationEventUIModel,
|
||||||
CoreApp,
|
CoreApp,
|
||||||
DashboardCursorSync,
|
DashboardCursorSync,
|
||||||
|
DataFrame,
|
||||||
EventFilterOptions,
|
EventFilterOptions,
|
||||||
FieldConfigSource,
|
FieldConfigSource,
|
||||||
getDataSourceRef,
|
getDataSourceRef,
|
||||||
@ -42,6 +43,7 @@ import { InspectTab } from 'app/features/inspector/types';
|
|||||||
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
import { getPanelLinksSupplier } from 'app/features/panel/panellinks/linkSuppliers';
|
||||||
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
|
||||||
import { applyFilterFromTable } from 'app/features/variables/adhoc/actions';
|
import { applyFilterFromTable } from 'app/features/variables/adhoc/actions';
|
||||||
|
import { onUpdatePanelSnapshotData } from 'app/plugins/datasource/grafana/utils';
|
||||||
import { changeSeriesColorConfigFactory } from 'app/plugins/panel/timeseries/overrides/colorSeriesConfigFactory';
|
import { changeSeriesColorConfigFactory } from 'app/plugins/panel/timeseries/overrides/colorSeriesConfigFactory';
|
||||||
import { dispatch } from 'app/store/store';
|
import { dispatch } from 'app/store/store';
|
||||||
import { RenderEvent } from 'app/types/events';
|
import { RenderEvent } from 'app/types/events';
|
||||||
@ -116,6 +118,7 @@ export class PanelStateWrapper extends PureComponent<Props, State> {
|
|||||||
canEditAnnotations: props.dashboard.canEditAnnotations.bind(props.dashboard),
|
canEditAnnotations: props.dashboard.canEditAnnotations.bind(props.dashboard),
|
||||||
canDeleteAnnotations: props.dashboard.canDeleteAnnotations.bind(props.dashboard),
|
canDeleteAnnotations: props.dashboard.canDeleteAnnotations.bind(props.dashboard),
|
||||||
onAddAdHocFilter: this.onAddAdHocFilter,
|
onAddAdHocFilter: this.onAddAdHocFilter,
|
||||||
|
onUpdateData: this.onUpdateData,
|
||||||
},
|
},
|
||||||
data: this.getInitialPanelDataState(),
|
data: this.getInitialPanelDataState(),
|
||||||
};
|
};
|
||||||
@ -146,6 +149,10 @@ export class PanelStateWrapper extends PureComponent<Props, State> {
|
|||||||
return CoreApp.Dashboard;
|
return CoreApp.Dashboard;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onUpdateData = (frames: DataFrame[]): Promise<boolean> => {
|
||||||
|
return onUpdatePanelSnapshotData(this.props.panel, frames);
|
||||||
|
};
|
||||||
|
|
||||||
onSeriesColorChange = (label: string, color: string) => {
|
onSeriesColorChange = (label: string, color: string) => {
|
||||||
this.onFieldConfigChange(changeSeriesColorConfigFactory(label, color, this.props.panel.fieldConfig));
|
this.onFieldConfigChange(changeSeriesColorConfigFactory(label, color, this.props.panel.fieldConfig));
|
||||||
};
|
};
|
||||||
|
@ -99,8 +99,6 @@ describe('DashboardLoader', () => {
|
|||||||
const loader = new DashboardLoader({});
|
const loader = new DashboardLoader({});
|
||||||
await loader.load('fake-dash');
|
await loader.load('fake-dash');
|
||||||
expect(loader.state.dashboard).toBeInstanceOf(DashboardScene);
|
expect(loader.state.dashboard).toBeInstanceOf(DashboardScene);
|
||||||
// @ts-expect-error - private
|
|
||||||
expect(loader.state.dashboard?.urlSyncManager).toBeDefined();
|
|
||||||
expect(loader.state.isLoading).toBe(false);
|
expect(loader.state.isLoading).toBe(false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
56
public/app/plugins/datasource/grafana/utils.ts
Normal file
56
public/app/plugins/datasource/grafana/utils.ts
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
import { DataFrame, DataFrameJSON, dataFrameToJSON } from '@grafana/data';
|
||||||
|
import appEvents from 'app/core/app_events';
|
||||||
|
import { GRAFANA_DATASOURCE_NAME } from 'app/features/alerting/unified/utils/datasource';
|
||||||
|
import { PanelModel } from 'app/features/dashboard/state';
|
||||||
|
import { ShowConfirmModalEvent } from 'app/types/events';
|
||||||
|
|
||||||
|
import { GrafanaQuery, GrafanaQueryType } from './types';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Will show a confirm modal if the current panel does not have a snapshot query.
|
||||||
|
* If the confirm modal is shown, and the user aborts the promise will resolve with a false value,
|
||||||
|
* otherwise it will resolve with a true value.
|
||||||
|
*/
|
||||||
|
export function onUpdatePanelSnapshotData(panel: PanelModel, frames: DataFrame[]): Promise<boolean> {
|
||||||
|
return new Promise<boolean>((resolve) => {
|
||||||
|
if (panel.datasource?.uid === GRAFANA_DATASOURCE_NAME) {
|
||||||
|
updateSnapshotData(frames, panel);
|
||||||
|
resolve(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
appEvents.publish(
|
||||||
|
new ShowConfirmModalEvent({
|
||||||
|
title: 'Change to panel embedded data',
|
||||||
|
text: 'If you want to change the data shown in this panel Grafana will need to remove the panels current query and replace it with a snapshot of the current data. This enabled you to edit the data',
|
||||||
|
yesText: 'Continue',
|
||||||
|
icon: 'pen',
|
||||||
|
onConfirm: () => {
|
||||||
|
updateSnapshotData(frames, panel);
|
||||||
|
resolve(true);
|
||||||
|
},
|
||||||
|
onDismiss: () => {
|
||||||
|
resolve(false);
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSnapshotData(frames: DataFrame[], panel: PanelModel) {
|
||||||
|
const snapshot: DataFrameJSON[] = frames.map((f) => dataFrameToJSON(f));
|
||||||
|
|
||||||
|
const query: GrafanaQuery = {
|
||||||
|
refId: 'A',
|
||||||
|
queryType: GrafanaQueryType.Snapshot,
|
||||||
|
snapshot,
|
||||||
|
datasource: { uid: GRAFANA_DATASOURCE_NAME },
|
||||||
|
};
|
||||||
|
|
||||||
|
panel.updateQueries({
|
||||||
|
dataSource: { uid: GRAFANA_DATASOURCE_NAME },
|
||||||
|
queries: [query],
|
||||||
|
});
|
||||||
|
|
||||||
|
panel.refresh();
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user