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