mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Scenes/VizPanel: Add support for panel repeat options (#81818)
This commit is contained in:
@@ -2,14 +2,15 @@ import * as H from 'history';
|
||||
|
||||
import { NavIndex } from '@grafana/data';
|
||||
import { config, locationService } from '@grafana/runtime';
|
||||
import { SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
import { SceneGridItem, SceneGridLayout, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes';
|
||||
|
||||
import { getDashboardSceneFor, getPanelIdForVizPanel } from '../utils/utils';
|
||||
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem';
|
||||
import { getPanelIdForVizPanel, getDashboardSceneFor } from '../utils/utils';
|
||||
|
||||
import { PanelDataPane } from './PanelDataPane/PanelDataPane';
|
||||
import { PanelEditorRenderer } from './PanelEditorRenderer';
|
||||
import { PanelOptionsPane } from './PanelOptionsPane';
|
||||
import { VizPanelManager } from './VizPanelManager';
|
||||
import { VizPanelManager, VizPanelManagerState } from './VizPanelManager';
|
||||
|
||||
export interface PanelEditorState extends SceneObjectState {
|
||||
isDirty?: boolean;
|
||||
@@ -20,12 +21,21 @@ export interface PanelEditorState extends SceneObjectState {
|
||||
}
|
||||
|
||||
export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
private _initialRepeatOptions: Pick<VizPanelManagerState, 'repeat' | 'repeatDirection' | 'maxPerRow'> = {};
|
||||
static Component = PanelEditorRenderer;
|
||||
|
||||
private _discardChanges = false;
|
||||
|
||||
public constructor(state: PanelEditorState) {
|
||||
super(state);
|
||||
|
||||
const { repeat, repeatDirection, maxPerRow } = state.vizManager.state;
|
||||
this._initialRepeatOptions = {
|
||||
repeat,
|
||||
repeatDirection,
|
||||
maxPerRow,
|
||||
};
|
||||
|
||||
this.addActivationHandler(this._activationHandler.bind(this));
|
||||
}
|
||||
|
||||
@@ -88,7 +98,104 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||
dashboard.onEnterEditMode();
|
||||
}
|
||||
|
||||
this.state.vizManager.commitChanges();
|
||||
const panelManager = this.state.vizManager;
|
||||
const sourcePanel = panelManager.state.sourcePanel.resolve();
|
||||
const sourcePanelParent = sourcePanel!.parent;
|
||||
|
||||
const normalToRepeat = !this._initialRepeatOptions.repeat && panelManager.state.repeat;
|
||||
const repeatToNormal = this._initialRepeatOptions.repeat && !panelManager.state.repeat;
|
||||
|
||||
if (sourcePanelParent instanceof SceneGridItem) {
|
||||
if (normalToRepeat) {
|
||||
this.replaceSceneGridItemWithPanelRepeater(sourcePanelParent);
|
||||
} else {
|
||||
panelManager.commitChanges();
|
||||
}
|
||||
} else if (sourcePanelParent instanceof PanelRepeaterGridItem) {
|
||||
if (repeatToNormal) {
|
||||
this.replacePanelRepeaterWithGridItem(sourcePanelParent);
|
||||
} else {
|
||||
this.handleRepeatOptionChanges(sourcePanelParent);
|
||||
}
|
||||
} else {
|
||||
console.error('Unsupported scene object type');
|
||||
}
|
||||
}
|
||||
|
||||
private replaceSceneGridItemWithPanelRepeater(gridItem: SceneGridItem) {
|
||||
const gridLayout = gridItem.parent;
|
||||
if (!(gridLayout instanceof SceneGridLayout)) {
|
||||
console.error('Expected grandparent to be SceneGridLayout!');
|
||||
return;
|
||||
}
|
||||
|
||||
const panelManager = this.state.vizManager;
|
||||
const repeatDirection = panelManager.state.repeatDirection ?? 'h';
|
||||
const repeater = new PanelRepeaterGridItem({
|
||||
key: gridItem.state.key,
|
||||
x: gridItem.state.x,
|
||||
y: gridItem.state.y,
|
||||
width: repeatDirection === 'h' ? 24 : gridItem.state.width,
|
||||
height: gridItem.state.height,
|
||||
itemHeight: gridItem.state.height,
|
||||
source: panelManager.state.panel.clone(),
|
||||
variableName: panelManager.state.repeat!,
|
||||
repeatedPanels: [],
|
||||
repeatDirection: panelManager.state.repeatDirection,
|
||||
maxPerRow: panelManager.state.maxPerRow,
|
||||
});
|
||||
gridLayout.setState({
|
||||
children: gridLayout.state.children.map((child) => (child.state.key === gridItem.state.key ? repeater : child)),
|
||||
});
|
||||
}
|
||||
|
||||
private replacePanelRepeaterWithGridItem(panelRepeater: PanelRepeaterGridItem) {
|
||||
const gridLayout = panelRepeater.parent;
|
||||
if (!(gridLayout instanceof SceneGridLayout)) {
|
||||
console.error('Expected grandparent to be SceneGridLayout!');
|
||||
return;
|
||||
}
|
||||
|
||||
const panelManager = this.state.vizManager;
|
||||
const panelClone = panelManager.state.panel.clone();
|
||||
const gridItem = new SceneGridItem({
|
||||
key: panelRepeater.state.key,
|
||||
x: panelRepeater.state.x,
|
||||
y: panelRepeater.state.y,
|
||||
width: this._initialRepeatOptions.repeatDirection === 'h' ? 8 : panelRepeater.state.width,
|
||||
height: this._initialRepeatOptions.repeatDirection === 'v' ? 8 : panelRepeater.state.height,
|
||||
body: panelClone,
|
||||
});
|
||||
gridLayout.setState({
|
||||
children: gridLayout.state.children.map((child) =>
|
||||
child.state.key === panelRepeater.state.key ? gridItem : child
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
private handleRepeatOptionChanges(panelRepeater: PanelRepeaterGridItem) {
|
||||
let width = panelRepeater.state.width ?? 1;
|
||||
let height = panelRepeater.state.height;
|
||||
|
||||
const panelManager = this.state.vizManager;
|
||||
const horizontalToVertical =
|
||||
this._initialRepeatOptions.repeatDirection === 'h' && panelManager.state.repeatDirection === 'v';
|
||||
const verticalToHorizontal =
|
||||
this._initialRepeatOptions.repeatDirection === 'v' && panelManager.state.repeatDirection === 'h';
|
||||
if (horizontalToVertical) {
|
||||
width = Math.floor(width / (panelRepeater.state.maxPerRow ?? 1));
|
||||
} else if (verticalToHorizontal) {
|
||||
width = 24;
|
||||
}
|
||||
|
||||
panelRepeater.setState({
|
||||
source: panelManager.state.panel.clone(),
|
||||
repeatDirection: panelManager.state.repeatDirection,
|
||||
variableName: panelManager.state.repeat,
|
||||
maxPerRow: panelManager.state.maxPerRow,
|
||||
width,
|
||||
height,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user