DashboardScene: Fixes issues with relative time range in panel edit (#86862)

* DashboardScene: Fixes deleting dirty dashboard

* Update

* Progress

* Update

* Update

* Update

* Update

* Update

* Update

* update

* Update
This commit is contained in:
Torkel Ödegaard 2024-04-29 10:53:57 +02:00 committed by GitHub
parent 01f8301504
commit a4bb4c8400
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 28 additions and 27 deletions

View File

@ -42,11 +42,19 @@ export class PanelDataQueriesTab extends SceneObjectBase<PanelDataQueriesTabStat
constructor(panelManager: VizPanelManager) {
super({});
this.TabComponent = (props: PanelDataTabHeaderProps) => {
return QueriesTab({ ...props, model: this });
};
this._panelManager = panelManager;
this.addActivationHandler(this.onActivate.bind(this));
}
private onActivate() {
// This is to preserve SceneQueryRunner stays alive when switching between visualizations and table view
const deactivate = this._panelManager.queryRunner.activate();
return () => deactivate();
}
buildQueryOptions(): QueryGroupOptions {
@ -179,7 +187,7 @@ export class PanelDataQueriesTab extends SceneObjectBase<PanelDataQueriesTabStat
function PanelDataQueriesTabRendered({ model }: SceneComponentProps<PanelDataQueriesTab>) {
const { datasource, dsSettings } = model.panelManager.useState();
const { data } = model.panelManager.queryRunner.useState();
const { data, queries } = model.panelManager.queryRunner.useState();
if (!datasource || !dsSettings || !data) {
return null;
@ -201,7 +209,7 @@ function PanelDataQueriesTabRendered({ model }: SceneComponentProps<PanelDataQue
<QueryEditorRows
data={data}
queries={model.getQueries()}
queries={queries}
dsSettings={dsSettings}
onAddQuery={model.onAddQuery}
onQueriesChange={model.onQueriesChange}

View File

@ -136,7 +136,7 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
}
panelRepeater.setState({
body: panelManager.getPanelCloneWithData(),
body: panelManager.state.panel.clone(),
repeatDirection: panelManager.state.repeatDirection,
variableName: panelManager.state.repeat,
maxPerRow: panelManager.state.maxPerRow,

View File

@ -22,7 +22,6 @@ import {
SceneObjectState,
SceneQueryRunner,
VizPanel,
sceneGraph,
sceneUtils,
} from '@grafana/scenes';
import { DataQuery, DataTransformerConfig, Panel } from '@grafana/schema';
@ -88,8 +87,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
repeatOptions = { repeat, repeatDirection, maxPerRow };
return new VizPanelManager({
panel: sourcePanel.clone({ $data: undefined }),
$data: sourcePanel.state.$data?.clone(),
panel: sourcePanel.clone(),
sourcePanel: sourcePanel.getRef(),
...repeatOptions,
});
@ -100,7 +98,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
}
private async loadDataSource() {
const dataObj = this.state.$data;
const dataObj = this.state.panel.state.$data;
if (!dataObj) {
return;
@ -207,14 +205,14 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
});
// When changing from non-data to data panel, we need to add a new data provider
if (!this.state.$data && !config.panels[pluginId].skipDataQuery) {
if (!this.state.panel.state.$data && !config.panels[pluginId].skipDataQuery) {
let ds = getLastUsedDatasourceFromStorage(getDashboardSceneFor(this).state.uid!)?.datasourceUid;
if (!ds) {
ds = config.defaultDatasource;
}
this.setState({
newPanel.setState({
$data: new SceneDataTransformer({
$data: new SceneQueryRunner({
datasource: {
@ -281,7 +279,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
public changeQueryOptions(options: QueryGroupOptions) {
const panelObj = this.state.panel;
const dataObj = this.queryRunner;
let timeRangeObj = sceneGraph.getTimeRange(panelObj);
const timeRangeObj = panelObj.state.$timeRange;
const dataObjStateUpdate: Partial<SceneQueryRunner['state']> = {};
const timeRangeObjStateUpdate: Partial<PanelTimeRangeState> = {};
@ -348,7 +346,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
get queryRunner(): SceneQueryRunner {
// Panel data object is always SceneQueryRunner wrapped in a SceneDataTransformer
const runner = getQueryRunnerFor(this);
const runner = getQueryRunnerFor(this.state.panel);
if (!runner) {
throw new Error('Query runner not found');
@ -358,7 +356,7 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
}
get dataTransformer(): SceneDataTransformer {
const provider = this.state.$data;
const provider = this.state.panel.state.$data;
if (!provider || !(provider instanceof SceneDataTransformer)) {
throw new Error('Could not find SceneDataTransformer for panel');
}
@ -376,6 +374,9 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
.setTitle('')
.setOption('showTypeIcons', true)
.setOption('showHeader', true)
// Here we are breaking a scene rule and changing the parent of the main panel data provider
// But we need to share this same instance as the queries tab is subscribing to it
.setData(this.dataTransformer)
.build(),
});
}
@ -415,23 +416,21 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
if (sourcePanel.parent instanceof DashboardGridItem) {
sourcePanel.parent.setState({
...repeatUpdate,
body: this.state.panel.clone({
$data: this.state.$data?.clone(),
}),
body: this.state.panel.clone(),
});
}
if (sourcePanel.parent instanceof LibraryVizPanel) {
if (sourcePanel.parent.parent instanceof DashboardGridItem) {
const newLibPanel = sourcePanel.parent.clone({
panel: this.state.panel.clone({
$data: this.state.$data?.clone(),
}),
panel: this.state.panel.clone(),
});
sourcePanel.parent.parent.setState({
body: newLibPanel,
...repeatUpdate,
});
updateLibraryVizPanel(newLibPanel!).then((p) => {
if (sourcePanel.parent instanceof LibraryVizPanel) {
newLibPanel.setPanelFromLibPanel(p);
@ -455,18 +454,12 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
}
const parentClone = gridItem.clone({
body: this.state.panel.clone({
$data: this.state.$data?.clone(),
}),
body: this.state.panel.clone(),
});
return gridItemToPanel(parentClone);
}
public getPanelCloneWithData(): VizPanel {
return this.state.panel.clone({ $data: this.state.$data?.clone() });
}
public setPanelTitle(newTitle: string) {
this.state.panel.setState({ title: newTitle, hoverHeader: newTitle === '' });
}

View File

@ -39,8 +39,8 @@ export class PanelTimeRange extends SceneTimeRangeTransformerBase<PanelTimeRange
this.subscribeToState((n, p) => {
// Listen to own changes and update time info when required
if (n.timeFrom !== p.timeFrom || n.timeShift !== p.timeShift) {
const { timeInfo } = this.getTimeOverride(this.getAncestorTimeRange().state.value);
this.setState({ timeInfo });
const { timeInfo, timeRange } = this.getTimeOverride(this.getAncestorTimeRange().state.value);
this.setState({ timeInfo, value: timeRange });
}
})
);