2023-09-11 13:51:05 +02:00
|
|
|
import * as H from 'history';
|
|
|
|
|
|
2023-11-02 20:02:25 +01:00
|
|
|
import { NavIndex } from '@grafana/data';
|
2023-09-11 13:51:05 +02:00
|
|
|
import { locationService } from '@grafana/runtime';
|
|
|
|
|
import {
|
|
|
|
|
getUrlSyncManager,
|
2023-12-07 10:25:06 +01:00
|
|
|
SceneFlexItem,
|
2023-09-11 13:51:05 +02:00
|
|
|
SceneFlexLayout,
|
2024-01-12 13:22:53 +00:00
|
|
|
SceneGridItem,
|
2023-09-11 13:51:05 +02:00
|
|
|
SceneObject,
|
|
|
|
|
SceneObjectBase,
|
|
|
|
|
SceneObjectRef,
|
|
|
|
|
SceneObjectState,
|
|
|
|
|
sceneUtils,
|
|
|
|
|
SplitLayout,
|
|
|
|
|
VizPanel,
|
|
|
|
|
} from '@grafana/scenes';
|
2023-12-19 14:51:19 +01:00
|
|
|
import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv';
|
2023-09-11 13:51:05 +02:00
|
|
|
|
|
|
|
|
import { DashboardScene } from '../scene/DashboardScene';
|
2023-12-19 14:51:19 +01:00
|
|
|
import { DashboardModelCompatibilityWrapper } from '../utils/DashboardModelCompatibilityWrapper';
|
2023-10-20 15:22:56 +02:00
|
|
|
import { getDashboardUrl } from '../utils/urlBuilders';
|
2023-09-11 13:51:05 +02:00
|
|
|
|
2023-12-07 10:25:06 +01:00
|
|
|
import { PanelDataPane } from './PanelDataPane/PanelDataPane';
|
2023-09-11 13:51:05 +02:00
|
|
|
import { PanelEditorRenderer } from './PanelEditorRenderer';
|
2023-12-19 14:51:19 +01:00
|
|
|
import { PanelEditorUrlSync } from './PanelEditorUrlSync';
|
2023-09-11 13:51:05 +02:00
|
|
|
import { PanelOptionsPane } from './PanelOptionsPane';
|
2023-12-06 16:14:54 +00:00
|
|
|
import { PanelVizTypePicker } from './PanelVizTypePicker';
|
|
|
|
|
import { VizPanelManager } from './VizPanelManager';
|
2023-09-11 13:51:05 +02:00
|
|
|
|
|
|
|
|
export interface PanelEditorState extends SceneObjectState {
|
|
|
|
|
body: SceneObject;
|
|
|
|
|
controls?: SceneObject[];
|
|
|
|
|
isDirty?: boolean;
|
|
|
|
|
/** Panel to inspect */
|
2023-12-19 14:51:19 +01:00
|
|
|
inspectPanelKey?: string;
|
2023-09-11 13:51:05 +02:00
|
|
|
/** Scene object that handles the current drawer */
|
2023-12-19 14:51:19 +01:00
|
|
|
overlay?: SceneObject;
|
2023-09-11 13:51:05 +02:00
|
|
|
|
|
|
|
|
dashboardRef: SceneObjectRef<DashboardScene>;
|
|
|
|
|
sourcePanelRef: SceneObjectRef<VizPanel>;
|
2023-12-06 16:14:54 +00:00
|
|
|
panelRef: SceneObjectRef<VizPanelManager>;
|
2023-09-11 13:51:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
|
|
|
|
static Component = PanelEditorRenderer;
|
|
|
|
|
|
2023-12-19 14:51:19 +01:00
|
|
|
/**
|
|
|
|
|
* Handles url sync
|
|
|
|
|
*/
|
|
|
|
|
protected _urlSync = new PanelEditorUrlSync(this);
|
|
|
|
|
|
2023-09-11 13:51:05 +02:00
|
|
|
public constructor(state: PanelEditorState) {
|
|
|
|
|
super(state);
|
|
|
|
|
|
|
|
|
|
this.addActivationHandler(() => this._activationHandler());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _activationHandler() {
|
2023-12-19 14:51:19 +01:00
|
|
|
const oldDashboardWrapper = new DashboardModelCompatibilityWrapper(this.state.dashboardRef.resolve());
|
|
|
|
|
// @ts-expect-error
|
|
|
|
|
getDashboardSrv().setCurrent(oldDashboardWrapper);
|
|
|
|
|
|
2023-09-11 13:51:05 +02:00
|
|
|
// Deactivation logic
|
|
|
|
|
return () => {
|
|
|
|
|
getUrlSyncManager().cleanUp(this);
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public startUrlSync() {
|
|
|
|
|
getUrlSyncManager().initSync(this);
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-02 20:02:25 +01:00
|
|
|
public getPageNav(location: H.Location, navIndex: NavIndex) {
|
2023-09-11 13:51:05 +02:00
|
|
|
return {
|
|
|
|
|
text: 'Edit panel',
|
2023-11-02 20:02:25 +01:00
|
|
|
parentItem: this.state.dashboardRef.resolve().getPageNav(location, navIndex),
|
2023-09-11 13:51:05 +02:00
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public onDiscard = () => {
|
|
|
|
|
// Open question on what to preserve when going back
|
|
|
|
|
// Preserve time range, and variables state (that might have been changed while in panel edit)
|
|
|
|
|
// Preserve current panel data? (say if you just changed the time range and have new data)
|
|
|
|
|
this._navigateBackToDashboard();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public onApply = () => {
|
|
|
|
|
this._commitChanges();
|
|
|
|
|
this._navigateBackToDashboard();
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
public onSave = () => {
|
|
|
|
|
this._commitChanges();
|
|
|
|
|
// Open dashboard save drawer
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
private _commitChanges() {
|
|
|
|
|
const dashboard = this.state.dashboardRef.resolve();
|
|
|
|
|
const sourcePanel = this.state.sourcePanelRef.resolve();
|
2023-12-19 14:51:19 +01:00
|
|
|
|
2023-09-11 13:51:05 +02:00
|
|
|
if (!dashboard.state.isEditing) {
|
|
|
|
|
dashboard.onEnterEditMode();
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-12 13:22:53 +00:00
|
|
|
const panelMngr = this.state.panelRef.resolve();
|
2023-12-19 14:51:19 +01:00
|
|
|
|
2024-01-12 13:22:53 +00:00
|
|
|
if (sourcePanel.parent instanceof SceneGridItem) {
|
|
|
|
|
sourcePanel.parent.setState({ body: panelMngr.state.panel.clone() });
|
|
|
|
|
}
|
2023-09-11 13:51:05 +02:00
|
|
|
|
|
|
|
|
// preserve time range and variables state
|
|
|
|
|
dashboard.setState({
|
|
|
|
|
$timeRange: this.state.$timeRange?.clone(),
|
|
|
|
|
$variables: this.state.$variables?.clone(),
|
|
|
|
|
isDirty: true,
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private _navigateBackToDashboard() {
|
|
|
|
|
locationService.push(
|
|
|
|
|
getDashboardUrl({
|
|
|
|
|
uid: this.state.dashboardRef.resolve().state.uid,
|
|
|
|
|
currentQueryParams: locationService.getLocation().search,
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export function buildPanelEditScene(dashboard: DashboardScene, panel: VizPanel): PanelEditor {
|
|
|
|
|
const panelClone = panel.clone();
|
2023-12-19 14:51:19 +01:00
|
|
|
|
2024-01-12 01:21:32 -08:00
|
|
|
const vizPanelMgr = new VizPanelManager(panelClone);
|
2023-09-11 13:51:05 +02:00
|
|
|
const dashboardStateCloned = sceneUtils.cloneSceneObjectState(dashboard.state);
|
|
|
|
|
|
|
|
|
|
return new PanelEditor({
|
2023-09-22 13:04:17 +02:00
|
|
|
dashboardRef: dashboard.getRef(),
|
|
|
|
|
sourcePanelRef: panel.getRef(),
|
2023-12-06 16:14:54 +00:00
|
|
|
panelRef: vizPanelMgr.getRef(),
|
2023-09-11 13:51:05 +02:00
|
|
|
controls: dashboardStateCloned.controls,
|
|
|
|
|
$variables: dashboardStateCloned.$variables,
|
|
|
|
|
$timeRange: dashboardStateCloned.$timeRange,
|
|
|
|
|
body: new SplitLayout({
|
|
|
|
|
direction: 'row',
|
2023-12-07 10:25:06 +01:00
|
|
|
primary: new SplitLayout({
|
2023-09-11 13:51:05 +02:00
|
|
|
direction: 'column',
|
2023-12-07 10:25:06 +01:00
|
|
|
primary: new SceneFlexLayout({
|
|
|
|
|
direction: 'column',
|
2024-01-15 16:43:30 +01:00
|
|
|
minHeight: 200,
|
2023-12-19 14:51:19 +01:00
|
|
|
children: [vizPanelMgr],
|
2023-12-07 10:25:06 +01:00
|
|
|
}),
|
|
|
|
|
secondary: new SceneFlexItem({
|
2023-12-19 14:51:19 +01:00
|
|
|
body: new PanelDataPane(vizPanelMgr),
|
2023-12-07 10:25:06 +01:00
|
|
|
}),
|
2023-09-11 13:51:05 +02:00
|
|
|
}),
|
2023-12-06 16:14:54 +00:00
|
|
|
secondary: new SceneFlexLayout({
|
|
|
|
|
direction: 'column',
|
|
|
|
|
children: [new PanelOptionsPane(vizPanelMgr), new PanelVizTypePicker(vizPanelMgr)],
|
2023-09-11 13:51:05 +02:00
|
|
|
}),
|
|
|
|
|
}),
|
|
|
|
|
});
|
|
|
|
|
}
|