mirror of https://github.com/grafana/grafana
DashboardScene: View panel scene (#78718)
* DashboardScene: View panel fixes * Update * Update * Update * works and added tests * Update * Updatepull/78902/head
parent
8e01932166
commit
d33a624ba6
@ -0,0 +1,71 @@ |
|||||||
|
import { |
||||||
|
LocalValueVariable, |
||||||
|
SceneGridItem, |
||||||
|
SceneGridLayout, |
||||||
|
SceneGridRow, |
||||||
|
SceneVariableSet, |
||||||
|
VizPanel, |
||||||
|
} from '@grafana/scenes'; |
||||||
|
|
||||||
|
import { DashboardScene } from './DashboardScene'; |
||||||
|
import { ViewPanelScene } from './ViewPanelScene'; |
||||||
|
|
||||||
|
describe('ViewPanelScene', () => { |
||||||
|
it('Should build scene on activate', () => { |
||||||
|
const { viewPanelScene } = buildScene(); |
||||||
|
viewPanelScene.activate(); |
||||||
|
expect(viewPanelScene.state.body).toBeDefined(); |
||||||
|
}); |
||||||
|
|
||||||
|
it('Should look copy row variable scope', () => { |
||||||
|
const { viewPanelScene } = buildScene({ rowVariables: true, panelVariables: true }); |
||||||
|
viewPanelScene.activate(); |
||||||
|
|
||||||
|
const variables = viewPanelScene.state.body?.state.$variables; |
||||||
|
expect(variables?.state.variables.length).toBe(2); |
||||||
|
}); |
||||||
|
}); |
||||||
|
|
||||||
|
interface SceneOptions { |
||||||
|
rowVariables?: boolean; |
||||||
|
panelVariables?: boolean; |
||||||
|
} |
||||||
|
|
||||||
|
function buildScene(options?: SceneOptions) { |
||||||
|
// builds a scene how it looks like after row and panel repeats are processed
|
||||||
|
const panel = new VizPanel({ |
||||||
|
key: 'panel-22', |
||||||
|
$variables: options?.panelVariables |
||||||
|
? new SceneVariableSet({ |
||||||
|
variables: [new LocalValueVariable({ value: 'panel-var-value' })], |
||||||
|
}) |
||||||
|
: undefined, |
||||||
|
}); |
||||||
|
|
||||||
|
const dashboard = new DashboardScene({ |
||||||
|
body: new SceneGridLayout({ |
||||||
|
children: [ |
||||||
|
new SceneGridRow({ |
||||||
|
x: 0, |
||||||
|
y: 10, |
||||||
|
width: 24, |
||||||
|
$variables: options?.rowVariables |
||||||
|
? new SceneVariableSet({ |
||||||
|
variables: [new LocalValueVariable({ value: 'row-var-value' })], |
||||||
|
}) |
||||||
|
: undefined, |
||||||
|
height: 1, |
||||||
|
children: [ |
||||||
|
new SceneGridItem({ |
||||||
|
body: panel, |
||||||
|
}), |
||||||
|
], |
||||||
|
}), |
||||||
|
], |
||||||
|
}), |
||||||
|
}); |
||||||
|
|
||||||
|
const viewPanelScene = new ViewPanelScene({ panelRef: panel.getRef() }); |
||||||
|
|
||||||
|
return { viewPanelScene, dashboard }; |
||||||
|
} |
@ -0,0 +1,95 @@ |
|||||||
|
import React from 'react'; |
||||||
|
|
||||||
|
import { |
||||||
|
SceneComponentProps, |
||||||
|
SceneObjectBase, |
||||||
|
SceneObjectRef, |
||||||
|
SceneObjectState, |
||||||
|
VizPanel, |
||||||
|
sceneUtils, |
||||||
|
SceneVariables, |
||||||
|
SceneGridRow, |
||||||
|
sceneGraph, |
||||||
|
SceneVariableSet, |
||||||
|
SceneVariable, |
||||||
|
} from '@grafana/scenes'; |
||||||
|
|
||||||
|
interface ViewPanelSceneState extends SceneObjectState { |
||||||
|
panelRef: SceneObjectRef<VizPanel>; |
||||||
|
body?: VizPanel; |
||||||
|
} |
||||||
|
|
||||||
|
export class ViewPanelScene extends SceneObjectBase<ViewPanelSceneState> { |
||||||
|
public constructor(state: ViewPanelSceneState) { |
||||||
|
super(state); |
||||||
|
|
||||||
|
this.addActivationHandler(this._activationHandler.bind(this)); |
||||||
|
} |
||||||
|
|
||||||
|
public _activationHandler() { |
||||||
|
const panel = this.state.panelRef.resolve(); |
||||||
|
const panelState = sceneUtils.cloneSceneObjectState(panel.state, { |
||||||
|
key: panel.state.key + '-view', |
||||||
|
$variables: this.getScopedVariables(panel), |
||||||
|
}); |
||||||
|
|
||||||
|
const body = new VizPanel(panelState); |
||||||
|
|
||||||
|
this.setState({ body }); |
||||||
|
|
||||||
|
return () => { |
||||||
|
// Make sure we preserve data state
|
||||||
|
if (body.state.$data) { |
||||||
|
panel.setState({ $data: body.state.$data.clone() }); |
||||||
|
} |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// In case the panel is inside a repeated row
|
||||||
|
private getScopedVariables(panel: VizPanel): SceneVariables | undefined { |
||||||
|
const row = tryGetParentRow(panel); |
||||||
|
const variables: SceneVariable[] = []; |
||||||
|
|
||||||
|
// Because we are rendering the panel outside it's potential row context we need to copy the row (scoped) varables
|
||||||
|
if (row && row.state.$variables) { |
||||||
|
for (const variable of row.state.$variables.state.variables) { |
||||||
|
variables.push(variable.clone()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// If we have local scoped panel variables we need to add the row variables to it
|
||||||
|
if (panel.state.$variables) { |
||||||
|
for (const variable of panel.state.$variables.state.variables) { |
||||||
|
variables.push(variable.clone()); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if (variables.length > 0) { |
||||||
|
return new SceneVariableSet({ variables }); |
||||||
|
} |
||||||
|
|
||||||
|
return undefined; |
||||||
|
} |
||||||
|
|
||||||
|
public getUrlKey() { |
||||||
|
return this.state.panelRef.resolve().state.key; |
||||||
|
} |
||||||
|
|
||||||
|
public static Component = ({ model }: SceneComponentProps<ViewPanelScene>) => { |
||||||
|
const { body } = model.useState(); |
||||||
|
|
||||||
|
if (!body) { |
||||||
|
return null; |
||||||
|
} |
||||||
|
|
||||||
|
return <body.Component model={body} />; |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
function tryGetParentRow(panel: VizPanel): SceneGridRow | undefined { |
||||||
|
try { |
||||||
|
return sceneGraph.getAncestor(panel, SceneGridRow); |
||||||
|
} catch { |
||||||
|
return undefined; |
||||||
|
} |
||||||
|
} |
Loading…
Reference in new issue