Update scenes to 0.2 (#65676)

* Update scenes to latest

* Replace FormatRegistryID with VariableFormatID

* Remove scene demos that were moved to scenes repo, fix the remaining demos

* Fix grafana Monitoring app

* DashboardsLoader migration

* Fix test
This commit is contained in:
Dominik Prokop 2023-03-31 09:59:06 +02:00 committed by GitHub
parent e0ef79f5cc
commit bbf74b941b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 665 additions and 942 deletions

View File

@ -267,7 +267,7 @@
"@grafana/lezer-logql": "0.1.2", "@grafana/lezer-logql": "0.1.2",
"@grafana/monaco-logql": "^0.0.7", "@grafana/monaco-logql": "^0.0.7",
"@grafana/runtime": "workspace:*", "@grafana/runtime": "workspace:*",
"@grafana/scenes": "^0.0.28", "@grafana/scenes": "^0.2.0",
"@grafana/schema": "workspace:*", "@grafana/schema": "workspace:*",
"@grafana/ui": "workspace:*", "@grafana/ui": "workspace:*",
"@kusto/monaco-kusto": "5.3.6", "@kusto/monaco-kusto": "5.3.6",

View File

@ -20,7 +20,7 @@ import {
VariableSuggestionsScope, VariableSuggestionsScope,
} from '@grafana/data'; } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime'; import { getTemplateSrv } from '@grafana/runtime';
import { FormatRegistryID } from '@grafana/scenes'; import { VariableFormatID } from '@grafana/schema';
import { getConfig } from 'app/core/config'; import { getConfig } from 'app/core/config';
import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv';
@ -305,7 +305,7 @@ export class LinkSrv implements LinkService {
}; };
if (replaceVariables) { if (replaceVariables) {
info.href = replaceVariables(info.href, undefined, FormatRegistryID.percentEncode); info.href = replaceVariables(info.href, undefined, VariableFormatID.PercentEncode);
info.title = replaceVariables(link.title); info.title = replaceVariables(link.title);
} }

View File

@ -9,6 +9,7 @@ import {
SceneRouteMatch, SceneRouteMatch,
EmbeddedScene, EmbeddedScene,
SceneAppPageLike, SceneAppPageLike,
SceneFlexItem,
} from '@grafana/scenes'; } from '@grafana/scenes';
import { usePageNav } from 'app/core/components/Page/usePageNav'; import { usePageNav } from 'app/core/components/Page/usePageNav';
import { PluginPageContext, PluginPageContextType } from 'app/features/plugins/components/PluginPageContext'; import { PluginPageContext, PluginPageContextType } from 'app/features/plugins/components/PluginPageContext';
@ -131,8 +132,10 @@ export function getSecondLevelDrilldown(
return new EmbeddedScene({ return new EmbeddedScene({
body: new SceneFlexLayout({ body: new SceneFlexLayout({
children: [ children: [
new SceneCanvasText({ new SceneFlexItem({
text: 'Drilldown: ' + secondLevel, body: new SceneCanvasText({
text: 'Drilldown: ' + secondLevel,
}),
}), }),
], ],
}), }),

View File

@ -15,6 +15,7 @@ import {
SceneControlsSpacer, SceneControlsSpacer,
SceneDataTransformer, SceneDataTransformer,
SceneRefreshPicker, SceneRefreshPicker,
SceneFlexItem,
} from '@grafana/scenes'; } from '@grafana/scenes';
import { PromQuery } from 'app/plugins/datasource/prometheus/types'; import { PromQuery } from 'app/plugins/datasource/prometheus/types';
@ -142,63 +143,70 @@ export function getHttpHandlerListScene(): EmbeddedScene {
children: [], children: [],
}), }),
getLayoutChild: (data, frame, frameIndex) => { getLayoutChild: (data, frame, frameIndex) => {
return new SceneFlexLayout({ return new SceneFlexItem({
key: `panel-${frameIndex}`, key: `panel-${frameIndex}`,
direction: 'row', minHeight: 200,
placement: { minHeight: 200 },
$data: new SceneDataNode({ $data: new SceneDataNode({
data: { data: {
...data, ...data,
series: [frame], series: [frame],
}, },
}), }),
children: [ body: new SceneFlexLayout({
new VizPanel({ direction: 'row',
pluginId: 'timeseries', children: [
// titleLink: { new SceneFlexItem({
// path: `/scenes/grafana-monitoring/handlers/${encodeURIComponent(frame.fields[1].labels.handler)}`, body: new VizPanel({
// queryKeys: ['from', 'to', 'var-instance'], pluginId: 'timeseries',
// }, // titleLink: {
title: getFrameDisplayName(frame), // path: `/scenes/grafana-monitoring/handlers/${encodeURIComponent(frame.fields[1].labels.handler)}`,
options: { // queryKeys: ['from', 'to', 'var-instance'],
legend: { displayMode: 'hidden' }, // },
}, title: getFrameDisplayName(frame),
}), options: {
new VizPanel({ legend: { displayMode: 'hidden' },
placement: { width: 200 }, },
title: 'Last', }),
pluginId: 'stat', }),
fieldConfig: {
defaults: { new SceneFlexItem({
displayName: 'Last', width: 200,
links: [ body: new VizPanel({
{ title: 'Last',
title: 'Go to handler drilldown view', pluginId: 'stat',
url: ``, fieldConfig: {
onBuildUrl: () => { defaults: {
const params = locationService.getSearchObject(); displayName: 'Last',
return getLinkUrlWithAppUrlState( links: [
'/scenes/grafana-monitoring/handlers/${__field.labels.handler:percentencode}', {
params title: 'Go to handler drilldown view',
); url: ``,
}, onBuildUrl: () => {
const params = locationService.getSearchObject();
return getLinkUrlWithAppUrlState(
'/scenes/grafana-monitoring/handlers/${__field.labels.handler:percentencode}',
params
);
},
},
],
}, },
], overrides: [],
}, },
overrides: [], options: {
}, graphMode: 'none',
options: { textMode: 'value',
graphMode: 'none', },
textMode: 'value', }),
}, }),
}), ],
], }),
}); });
}, },
}); });
const layout = new SceneFlexLayout({ const layout = new SceneFlexLayout({
children: [httpHandlersTable], children: [new SceneFlexItem({ body: httpHandlersTable })],
}); });
const sceneToggle = new SceneRadioToggle({ const sceneToggle = new SceneRadioToggle({
@ -209,7 +217,7 @@ export function getHttpHandlerListScene(): EmbeddedScene {
value: 'table', value: 'table',
onChange: (value) => { onChange: (value) => {
if (value === 'table') { if (value === 'table') {
layout.setState({ children: [httpHandlersTable] }); layout.setState({ children: [new SceneFlexItem({ body: httpHandlersTable })] });
} else { } else {
layout.setState({ children: [graphsScene] }); layout.setState({ children: [graphsScene] });
} }
@ -257,20 +265,23 @@ export function getHandlerDetailsScene(handler: string): EmbeddedScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'column', direction: 'column',
children: [ children: [
new VizPanel({ new SceneFlexItem({
$data: reqDurationTimeSeries, body: new VizPanel({
pluginId: 'timeseries', $data: reqDurationTimeSeries,
title: 'Request duration avg (ms)', pluginId: 'timeseries',
placement: {}, title: 'Request duration avg (ms)',
//displayMode: 'transparent', //displayMode: 'transparent',
options: {}, options: {},
}),
}), }),
new VizPanel({ new SceneFlexItem({
$data: reqCountTimeSeries, body: new VizPanel({
pluginId: 'timeseries', $data: reqCountTimeSeries,
title: 'Request count/s', pluginId: 'timeseries',
//displayMode: 'transparent', title: 'Request count/s',
options: {}, //displayMode: 'transparent',
options: {},
}),
}), }),
], ],
}), }),
@ -322,79 +333,94 @@ export function getOverviewScene(): EmbeddedScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'column', direction: 'column',
children: [ children: [
new SceneFlexLayout({ new SceneFlexItem({
placement: { height: 150 }, height: 150,
children: [ body: new SceneFlexLayout({
getInstantStatPanel('grafana_stat_totals_dashboard', 'Dashboards'), children: [
getInstantStatPanel('grafana_stat_total_users', 'Users'), new SceneFlexItem({
getInstantStatPanel('sum(grafana_stat_totals_datasource)', 'Data sources'), body: getInstantStatPanel('grafana_stat_totals_dashboard', 'Dashboards'),
getInstantStatPanel('grafana_stat_total_service_account_tokens', 'Service account tokens'), }),
], new SceneFlexItem({
}), body: getInstantStatPanel('grafana_stat_total_users', 'Users'),
new VizPanel({ }),
$data: new SceneQueryRunner({ new SceneFlexItem({
datasource: { uid: 'gdev-prometheus' }, body: getInstantStatPanel('sum(grafana_stat_totals_datasource)', 'Data sources'),
queries: [ }),
{ new SceneFlexItem({
refId: 'A', body: getInstantStatPanel('grafana_stat_total_service_account_tokens', 'Service account tokens'),
expr: `sum(process_resident_memory_bytes{job="grafana", instance=~"$instance"})`, }),
range: true,
format: 'time_series',
maxDataPoints: 500,
},
], ],
}), }),
pluginId: 'timeseries',
title: 'Memory usage',
options: {
legend: {
showLegend: false,
},
},
fieldConfig: {
defaults: {
unit: 'bytes',
min: 0,
custom: {
lineWidth: 2,
fillOpacity: 6,
//gradientMode: 'opacity',
},
},
overrides: [],
},
}), }),
new VizPanel({
$data: new SceneQueryRunner({ new SceneFlexItem({
datasource: { uid: 'gdev-prometheus' }, body: new VizPanel({
queries: [ $data: new SceneQueryRunner({
{ datasource: { uid: 'gdev-prometheus' },
refId: 'A', queries: [
expr: `sum(go_goroutines{job="grafana", instance=~"$instance"})`, {
range: true, refId: 'A',
format: 'time_series', expr: `sum(process_resident_memory_bytes{job="grafana", instance=~"$instance"})`,
maxDataPoints: 500, range: true,
format: 'time_series',
maxDataPoints: 500,
},
],
}),
pluginId: 'timeseries',
title: 'Memory usage',
options: {
legend: {
showLegend: false,
}, },
], },
fieldConfig: {
defaults: {
unit: 'bytes',
min: 0,
custom: {
lineWidth: 2,
fillOpacity: 6,
//gradientMode: 'opacity',
},
},
overrides: [],
},
}), }),
pluginId: 'timeseries', }),
title: 'Go routines', new SceneFlexItem({
options: { body: new VizPanel({
legend: { $data: new SceneQueryRunner({
showLegend: false, datasource: { uid: 'gdev-prometheus' },
}, queries: [
}, {
fieldConfig: { refId: 'A',
defaults: { expr: `sum(go_goroutines{job="grafana", instance=~"$instance"})`,
min: 0, range: true,
custom: { format: 'time_series',
lineWidth: 2, maxDataPoints: 500,
fillOpacity: 6, },
//gradientMode: 'opacity', ],
}),
pluginId: 'timeseries',
title: 'Go routines',
options: {
legend: {
showLegend: false,
}, },
}, },
overrides: [], fieldConfig: {
}, defaults: {
min: 0,
custom: {
lineWidth: 2,
fillOpacity: 6,
//gradientMode: 'opacity',
},
},
overrides: [],
},
}),
}), }),
], ],
}), }),
@ -455,31 +481,35 @@ export function getHandlerLogsScene(handler: string): EmbeddedScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'column', direction: 'column',
children: [ children: [
new VizPanel({ new SceneFlexItem({
pluginId: 'text', body: new VizPanel({
title: '', pluginId: 'text',
options: { title: '',
mode: 'markdown', options: {
content: ` mode: 'markdown',
[mupp](/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}/logs/mupp) content: `
[mapp](/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}/logs/mapp) [mupp](/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}/logs/mupp)
`, [mapp](/scenes/grafana-monitoring/handlers/${encodeURIComponent(handler)}/logs/mapp)
}, `,
},
}),
}), }),
new VizPanel({ new SceneFlexItem({
$data: logsQuery, body: new VizPanel({
pluginId: 'logs', $data: logsQuery,
title: '', pluginId: 'logs',
options: { title: '',
showTime: true, options: {
showLabels: false, showTime: true,
showCommonLabels: false, showLabels: false,
wrapLogMessage: true, showCommonLabels: false,
prettifyLogMessage: false, wrapLogMessage: true,
enableLogDetails: true, prettifyLogMessage: false,
dedupStrategy: 'none', enableLogDetails: true,
sortOrder: 'Descending', dedupStrategy: 'none',
}, sortOrder: 'Descending',
},
}),
}), }),
], ],
}), }),
@ -513,20 +543,22 @@ export function getOverviewLogsScene(): EmbeddedScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'column', direction: 'column',
children: [ children: [
new VizPanel({ new SceneFlexItem({
$data: logsQuery, body: new VizPanel({
pluginId: 'logs', $data: logsQuery,
title: '', pluginId: 'logs',
options: { title: '',
showTime: true, options: {
showLabels: false, showTime: true,
showCommonLabels: false, showLabels: false,
wrapLogMessage: true, showCommonLabels: false,
prettifyLogMessage: false, wrapLogMessage: true,
enableLogDetails: true, prettifyLogMessage: false,
dedupStrategy: 'none', enableLogDetails: true,
sortOrder: 'Descending', dedupStrategy: 'none',
}, sortOrder: 'Descending',
},
}),
}), }),
], ],
}), }),

View File

@ -3,6 +3,7 @@ import {
DataSourceVariable, DataSourceVariable,
QueryVariable, QueryVariable,
SceneDataTransformer, SceneDataTransformer,
SceneGridItem,
SceneGridLayout, SceneGridLayout,
SceneGridRow, SceneGridRow,
SceneQueryRunner, SceneQueryRunner,
@ -169,10 +170,10 @@ describe('DashboardLoader', () => {
const rowScene = body.state.children[0] as SceneGridRow; const rowScene = body.state.children[0] as SceneGridRow;
expect(rowScene).toBeInstanceOf(SceneGridRow); expect(rowScene).toBeInstanceOf(SceneGridRow);
expect(rowScene.state.title).toEqual(row.title); expect(rowScene.state.title).toEqual(row.title);
expect(rowScene.state.placement?.y).toEqual(row.gridPos!.y); expect(rowScene.state.y).toEqual(row.gridPos!.y);
expect(rowScene.state.isCollapsed).toEqual(row.collapsed); expect(rowScene.state.isCollapsed).toEqual(row.collapsed);
expect(rowScene.state.children).toHaveLength(1); expect(rowScene.state.children).toHaveLength(1);
expect(rowScene.state.children[0]).toBeInstanceOf(VizPanel); expect(rowScene.state.children[0]).toBeInstanceOf(SceneGridItem);
}); });
it('should create panels within expanded row', () => { it('should create panels within expanded row', () => {
@ -233,18 +234,18 @@ describe('DashboardLoader', () => {
expect(body.state.children).toHaveLength(3); expect(body.state.children).toHaveLength(3);
expect(body).toBeInstanceOf(SceneGridLayout); expect(body).toBeInstanceOf(SceneGridLayout);
// Panel out of row // Panel out of row
expect(body.state.children[0]).toBeInstanceOf(VizPanel); expect(body.state.children[0]).toBeInstanceOf(SceneGridItem);
const panelOutOfRowVizPanel = body.state.children[0] as VizPanel; const panelOutOfRowVizPanel = body.state.children[0] as SceneGridItem;
expect(panelOutOfRowVizPanel.state.title).toBe(panelOutOfRow.title); expect((panelOutOfRowVizPanel.state.body as VizPanel)?.state.title).toBe(panelOutOfRow.title);
// Row with panel // Row with panel
expect(body.state.children[1]).toBeInstanceOf(SceneGridRow); expect(body.state.children[1]).toBeInstanceOf(SceneGridRow);
const rowWithPanelsScene = body.state.children[1] as SceneGridRow; const rowWithPanelsScene = body.state.children[1] as SceneGridRow;
expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title); expect(rowWithPanelsScene.state.title).toBe(rowWithPanel.title);
expect(rowWithPanelsScene.state.children).toHaveLength(1); expect(rowWithPanelsScene.state.children).toHaveLength(1);
// Panel within row // Panel within row
expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(VizPanel); expect(rowWithPanelsScene.state.children[0]).toBeInstanceOf(SceneGridItem);
const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as VizPanel; const panelInRowVizPanel = rowWithPanelsScene.state.children[0] as SceneGridItem;
expect(panelInRowVizPanel.state.title).toBe(panelInRow.title); expect((panelInRowVizPanel.state.body as VizPanel).state.title).toBe(panelInRow.title);
// Empty row // Empty row
expect(body.state.children[2]).toBeInstanceOf(SceneGridRow); expect(body.state.children[2]).toBeInstanceOf(SceneGridRow);
const emptyRowScene = body.state.children[2] as SceneGridRow; const emptyRowScene = body.state.children[2] as SceneGridRow;
@ -295,22 +296,23 @@ describe('DashboardLoader', () => {
], ],
}; };
const vizPanelSceneObject = createVizPanelFromPanelModel(new PanelModel(panel)); const vizPanelSceneObject = createVizPanelFromPanelModel(new PanelModel(panel));
const vizPanelItelf = vizPanelSceneObject.state.body as VizPanel;
expect(vizPanelSceneObject.state.title).toBe('test'); expect(vizPanelItelf?.state.title).toBe('test');
expect(vizPanelSceneObject.state.pluginId).toBe('test-plugin'); expect(vizPanelItelf?.state.pluginId).toBe('test-plugin');
expect(vizPanelSceneObject.state.placement).toEqual({ x: 0, y: 0, width: 12, height: 8 }); expect(vizPanelSceneObject.state.x).toEqual(0);
expect(vizPanelSceneObject.state.options).toEqual(panel.options); expect(vizPanelSceneObject.state.y).toEqual(0);
expect(vizPanelSceneObject.state.fieldConfig).toEqual(panel.fieldConfig); expect(vizPanelSceneObject.state.width).toEqual(12);
expect(vizPanelSceneObject.state.pluginVersion).toBe('1.0.0'); expect(vizPanelSceneObject.state.height).toEqual(8);
expect(vizPanelItelf?.state.options).toEqual(panel.options);
expect(vizPanelItelf?.state.fieldConfig).toEqual(panel.fieldConfig);
expect(vizPanelItelf?.state.pluginVersion).toBe('1.0.0');
expect( expect(
((vizPanelSceneObject.state.$data as SceneDataTransformer)?.state.$data as SceneQueryRunner).state.queries ((vizPanelItelf.state.$data as SceneDataTransformer)?.state.$data as SceneQueryRunner).state.queries
).toEqual(panel.targets); ).toEqual(panel.targets);
expect( expect(
((vizPanelSceneObject.state.$data as SceneDataTransformer)?.state.$data as SceneQueryRunner).state.maxDataPoints ((vizPanelItelf.state.$data as SceneDataTransformer)?.state.$data as SceneQueryRunner).state.maxDataPoints
).toEqual(100); ).toEqual(100);
expect((vizPanelSceneObject.state.$data as SceneDataTransformer)?.state.transformations).toEqual( expect((vizPanelItelf.state.$data as SceneDataTransformer)?.state.transformations).toEqual(panel.transformations);
panel.transformations
);
}); });
it('should initalize the VizPanel without title and transparent true', () => { it('should initalize the VizPanel without title and transparent true', () => {
@ -323,8 +325,8 @@ describe('DashboardLoader', () => {
const vizPanelSceneObject = createVizPanelFromPanelModel(new PanelModel(panel)); const vizPanelSceneObject = createVizPanelFromPanelModel(new PanelModel(panel));
expect(vizPanelSceneObject.state.displayMode).toEqual('transparent'); expect((vizPanelSceneObject.state.body as VizPanel)?.state.displayMode).toEqual('transparent');
expect(vizPanelSceneObject.state.hoverHeader).toEqual(true); expect((vizPanelSceneObject.state.body as VizPanel)?.state.hoverHeader).toEqual(true);
}); });
}); });
@ -586,7 +588,7 @@ describe('DashboardLoader', () => {
hide: 2, hide: 2,
label: 'constant', label: 'constant',
name: 'constant', name: 'constant',
skipUrlSync: false, skipUrlSync: true,
type: 'constant', type: 'constant',
value: 'test', value: 'test',
}); });

View File

@ -11,7 +11,6 @@ import {
SceneGridLayout, SceneGridLayout,
SceneGridRow, SceneGridRow,
SceneTimeRange, SceneTimeRange,
SceneObject,
SceneQueryRunner, SceneQueryRunner,
SceneVariableSet, SceneVariableSet,
VariableValueSelectors, VariableValueSelectors,
@ -21,6 +20,7 @@ import {
QueryVariable, QueryVariable,
ConstantVariable, ConstantVariable,
SceneDataTransformer, SceneDataTransformer,
SceneGridItem,
} from '@grafana/scenes'; } from '@grafana/scenes';
import { StateManagerBase } from 'app/core/services/StateManagerBase'; import { StateManagerBase } from 'app/core/services/StateManagerBase';
import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv'; import { dashboardLoaderSrv } from 'app/features/dashboard/services/DashboardLoaderSrv';
@ -81,14 +81,14 @@ export class DashboardLoader extends StateManagerBase<DashboardLoaderState> {
} }
} }
export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneObject[] { export function createSceneObjectsForPanels(oldPanels: PanelModel[]): Array<SceneGridItem | SceneGridRow> {
// collects all panels and rows // collects all panels and rows
const panels: SceneObject[] = []; const panels: Array<SceneGridItem | SceneGridRow> = [];
// indicates expanded row that's currently processed // indicates expanded row that's currently processed
let currentRow: PanelModel | null = null; let currentRow: PanelModel | null = null;
// collects panels in the currently processed, expanded row // collects panels in the currently processed, expanded row
let currentRowPanels: SceneObject[] = []; let currentRowPanels: SceneGridItem[] = [];
for (const panel of oldPanels) { for (const panel of oldPanels) {
if (panel.type === 'row') { if (panel.type === 'row') {
@ -99,9 +99,7 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneObjec
new SceneGridRow({ new SceneGridRow({
title: panel.title, title: panel.title,
isCollapsed: true, isCollapsed: true,
placement: { y: panel.gridPos.y,
y: panel.gridPos.y,
},
children: panel.panels ? panel.panels.map(createVizPanelFromPanelModel) : [], children: panel.panels ? panel.panels.map(createVizPanelFromPanelModel) : [],
}) })
); );
@ -116,9 +114,7 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneObjec
panels.push( panels.push(
new SceneGridRow({ new SceneGridRow({
title: currentRow!.title, title: currentRow!.title,
placement: { y: currentRow.gridPos.y,
y: currentRow.gridPos.y,
},
children: currentRowPanels, children: currentRowPanels,
}) })
); );
@ -144,9 +140,7 @@ export function createSceneObjectsForPanels(oldPanels: PanelModel[]): SceneObjec
panels.push( panels.push(
new SceneGridRow({ new SceneGridRow({
title: currentRow!.title, title: currentRow!.title,
placement: { y: currentRow.gridPos.y,
y: currentRow.gridPos.y,
},
children: currentRowPanels, children: currentRowPanels,
}) })
); );
@ -263,27 +257,29 @@ export function createVizPanelFromPanelModel(panel: PanelModel) {
maxDataPoints: panel.maxDataPoints ?? undefined, maxDataPoints: panel.maxDataPoints ?? undefined,
}); });
return new VizPanel({ return new SceneGridItem({
title: panel.title, x: panel.gridPos.x,
pluginId: panel.type, y: panel.gridPos.y,
placement: { width: panel.gridPos.w,
x: panel.gridPos.x, height: panel.gridPos.h,
y: panel.gridPos.y, isDraggable: true,
width: panel.gridPos.w, isResizable: true,
height: panel.gridPos.h, body: new VizPanel({
}, title: panel.title,
options: panel.options ?? {}, pluginId: panel.type,
fieldConfig: panel.fieldConfig, options: panel.options ?? {},
pluginVersion: panel.pluginVersion, fieldConfig: panel.fieldConfig,
displayMode: panel.transparent ? 'transparent' : undefined, pluginVersion: panel.pluginVersion,
// To be replaced with it's own option persited option instead derived displayMode: panel.transparent ? 'transparent' : undefined,
hoverHeader: !panel.title && !panel.timeFrom && !panel.timeShift, // To be replaced with it's own option persited option instead derived
$data: panel.transformations?.length hoverHeader: !panel.title && !panel.timeFrom && !panel.timeShift,
? new SceneDataTransformer({ $data: panel.transformations?.length
$data: queryRunner, ? new SceneDataTransformer({
transformations: panel.transformations, $data: queryRunner,
}) transformations: panel.transformations,
: queryRunner, })
: queryRunner,
}),
}); });
} }

View File

@ -1,187 +0,0 @@
import { getFrameDisplayName } from '@grafana/data';
import {
SceneFlexLayout,
SceneTimeRange,
SceneTimePicker,
SceneByFrameRepeater,
VizPanel,
SceneCanvasText,
SceneToolbarInput,
SceneDataNode,
} from '@grafana/scenes';
import { TestDataQueryType } from 'app/plugins/datasource/testdata/dataquery.gen';
import { panelBuilders } from '../builders/panelBuilders';
import { DashboardScene } from '../dashboard/DashboardScene';
import { getQueryRunnerWithRandomWalkQuery } from './queries';
export function getFlexLayoutTest(): DashboardScene {
return new DashboardScene({
title: 'Flex layout test',
body: new SceneFlexLayout({
direction: 'row',
children: [
panelBuilders.newGraph({
placement: { minWidth: '70%' },
title: 'Dynamic height and width',
$data: getQueryRunnerWithRandomWalkQuery({}, { maxDataPointsFromWidth: true }),
}),
new SceneFlexLayout({
direction: 'column',
children: [
panelBuilders.newGraph({
title: 'Fill height',
options: {},
fieldConfig: {
defaults: {
custom: {
fillOpacity: 20,
},
},
overrides: [],
},
}),
panelBuilders.newGraph({
title: 'Fill height',
}),
new SceneCanvasText({
placement: { ySizing: 'content' },
text: 'Size to content',
fontSize: 20,
align: 'center',
}),
panelBuilders.newGraph({
title: 'Fixed height',
placement: { height: 300 },
}),
],
}),
],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
}
export function getScenePanelRepeaterTest(): DashboardScene {
const queryRunner = getQueryRunnerWithRandomWalkQuery({
seriesCount: 2,
alias: '__server_names',
scenarioId: TestDataQueryType.RandomWalk,
});
return new DashboardScene({
title: 'Panel repeater test',
body: new SceneByFrameRepeater({
body: new SceneFlexLayout({
direction: 'column',
children: [],
}),
getLayoutChild: (data, frame, frameIndex) => {
return new SceneFlexLayout({
key: `panel-${frameIndex}`,
$data: new SceneDataNode({
data: {
...data,
series: [frame],
},
}),
direction: 'row',
placement: { minHeight: 200 },
children: [
new VizPanel({
pluginId: 'timeseries',
title: getFrameDisplayName(frame),
options: {
legend: { displayMode: 'hidden' },
},
}),
new VizPanel({
placement: { width: 300 },
pluginId: 'stat',
fieldConfig: { defaults: { displayName: 'Last' }, overrides: [] },
options: {
graphMode: 'none',
},
}),
],
});
},
}),
$timeRange: new SceneTimeRange(),
$data: queryRunner,
actions: [
new SceneToolbarInput({
value: '2',
onChange: (newValue) => {
queryRunner.setState({
queries: [
{
...queryRunner.state.queries[0],
seriesCount: newValue,
},
],
});
queryRunner.runQueries();
},
}),
new SceneTimePicker({}),
],
});
}
export function getRepeaterSceneWithFlexWrap(): DashboardScene {
const queryRunner = getQueryRunnerWithRandomWalkQuery({
seriesCount: 10,
alias: '__server_names',
scenarioId: TestDataQueryType.RandomWalk,
});
return new DashboardScene({
title: 'Flex layout with wrap test',
body: new SceneByFrameRepeater({
body: new SceneFlexLayout({
direction: 'row',
wrap: 'wrap',
children: [],
}),
getLayoutChild: (data, frame, frameIndex) => {
return new VizPanel({
pluginId: 'timeseries',
title: getFrameDisplayName(frame),
$data: new SceneDataNode({
data: {
...data,
series: [frame],
},
}),
placement: { height: 300, minWidth: 400 },
options: {
legend: { displayMode: 'hidden' },
},
});
},
}),
$timeRange: new SceneTimeRange(),
$data: queryRunner,
actions: [
new SceneToolbarInput({
value: '10',
onChange: (newValue) => {
queryRunner.setState({
queries: [
{
...queryRunner.state.queries[0],
seriesCount: newValue,
},
],
});
queryRunner.runQueries();
},
}),
new SceneTimePicker({}),
],
});
}

View File

@ -1,53 +0,0 @@
import { VizPanel, SceneTimePicker, SceneFlexLayout, SceneGridLayout, SceneTimeRange } from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene';
import { getQueryRunnerWithRandomWalkQuery } from './queries';
export function getGridLayoutTest(): DashboardScene {
return new DashboardScene({
title: 'Grid layout test',
body: new SceneGridLayout({
children: [
new VizPanel({
pluginId: 'timeseries',
title: 'Draggable and resizable',
placement: {
x: 0,
y: 0,
width: 12,
height: 10,
isResizable: true,
isDraggable: true,
},
}),
new VizPanel({
pluginId: 'timeseries',
title: 'No drag and no resize',
placement: { x: 12, y: 0, width: 12, height: 10, isResizable: false, isDraggable: false },
}),
new SceneFlexLayout({
direction: 'column',
placement: { x: 6, y: 11, width: 12, height: 10, isDraggable: true, isResizable: true },
children: [
new VizPanel({
placement: { ySizing: 'fill' },
pluginId: 'timeseries',
title: 'Child of flex layout',
}),
new VizPanel({
placement: { ySizing: 'fill' },
pluginId: 'timeseries',
title: 'Child of flex layout',
}),
],
}),
],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
}

View File

@ -1,4 +1,11 @@
import { VizPanel, SceneGridRow, SceneTimePicker, SceneGridLayout, SceneTimeRange } from '@grafana/scenes'; import {
VizPanel,
SceneGridRow,
SceneTimePicker,
SceneGridLayout,
SceneTimeRange,
SceneGridItem,
} from '@grafana/scenes';
import { TestDataQueryType } from 'app/plugins/datasource/testdata/dataquery.gen'; import { TestDataQueryType } from 'app/plugins/datasource/testdata/dataquery.gen';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -22,36 +29,49 @@ export function getGridWithMultipleTimeRanges(): DashboardScene {
title: 'Row A - has its own query, last year time range', title: 'Row A - has its own query, last year time range',
key: 'Row A', key: 'Row A',
isCollapsed: true, isCollapsed: true,
placement: { y: 0 }, y: 0,
children: [ children: [
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 0,
title: 'Row A Child1', y: 1,
key: 'Row A Child1', width: 12,
placement: { x: 0, y: 1, width: 12, height: 5, isResizable: true, isDraggable: true }, height: 5,
isResizable: true,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child1',
key: 'Row A Child1',
}),
}), }),
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 0,
title: 'Row A Child2', y: 5,
key: 'Row A Child2', width: 6,
placement: { x: 0, y: 5, width: 6, height: 5, isResizable: true, isDraggable: true }, height: 5,
isResizable: true,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child2',
key: 'Row A Child2',
}),
}), }),
], ],
}), }),
new SceneGridItem({
new VizPanel({ x: 0,
$data: getQueryRunnerWithRandomWalkQuery(), y: 12,
pluginId: 'timeseries', width: 6,
title: 'Outsider, has its own query', height: 10,
key: 'Outsider-own-query', isResizable: true,
placement: { isDraggable: true,
x: 0, body: new VizPanel({
y: 12, $data: getQueryRunnerWithRandomWalkQuery(),
width: 6, pluginId: 'timeseries',
height: 10, title: 'Outsider, has its own query',
isResizable: true, key: 'Outsider-own-query',
isDraggable: true, }),
},
}), }),
], ],
}), }),

View File

@ -1,4 +1,12 @@
import { VizPanel, SceneTimePicker, SceneFlexLayout, SceneGridLayout, SceneTimeRange } from '@grafana/scenes'; import {
VizPanel,
SceneTimePicker,
SceneFlexLayout,
SceneGridLayout,
SceneTimeRange,
SceneGridItem,
SceneFlexItem,
} from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -9,79 +17,119 @@ export function getMultipleGridLayoutTest(): DashboardScene {
title: 'Multiple grid layouts test', title: 'Multiple grid layouts test',
body: new SceneFlexLayout({ body: new SceneFlexLayout({
children: [ children: [
new SceneGridLayout({ new SceneFlexItem({
children: [ body: new SceneGridLayout({
new VizPanel({ children: [
placement: { new SceneGridItem({
x: 0, x: 0,
y: 0, y: 0,
width: 12, width: 12,
height: 10, height: 10,
isDraggable: true, isDraggable: true,
isResizable: true, isResizable: true,
}, body: new VizPanel({
pluginId: 'timeseries',
title: 'Dragabble and resizable',
}),
new VizPanel({
placement: { x: 12, y: 0, width: 12, height: 10, isResizable: false, isDraggable: true },
pluginId: 'timeseries',
title: 'Draggable only',
}),
new SceneFlexLayout({
placement: { x: 6, y: 11, width: 12, height: 10, isResizable: false, isDraggable: true },
direction: 'column',
children: [
new VizPanel({
placement: { ySizing: 'fill' },
pluginId: 'timeseries', pluginId: 'timeseries',
title: 'Fill height', title: 'Dragabble and resizable',
}), }),
new VizPanel({ }),
placement: { ySizing: 'fill' }, new SceneGridItem({
x: 12,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries', pluginId: 'timeseries',
title: 'Fill height', title: 'Draggable only',
}), }),
], }),
}), new SceneGridItem({
], x: 6,
y: 11,
width: 12,
height: 10,
isResizable: false,
isDraggable: true,
body: new SceneFlexLayout({
direction: 'column',
children: [
new SceneFlexItem({
ySizing: 'fill',
body: new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
}),
new SceneFlexItem({
ySizing: 'fill',
body: new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
}),
],
}),
}),
],
}),
}), }),
new SceneFlexItem({
new SceneGridLayout({ body: new SceneGridLayout({
children: [ children: [
new VizPanel({ new SceneGridItem({
placement: {
x: 0, x: 0,
y: 0, y: 0,
width: 12, width: 12,
height: 10, height: 10,
isDraggable: true, isDraggable: true,
}, isResizable: true,
pluginId: 'timeseries', body: new VizPanel({
title: 'Fill height',
}),
new VizPanel({
placement: { x: 12, y: 0, width: 12, height: 10, isResizable: false, isDraggable: true },
pluginId: 'timeseries',
title: 'Fill height',
}),
new SceneFlexLayout({
placement: { x: 6, y: 11, width: 12, height: 10 },
direction: 'column',
children: [
new VizPanel({
placement: { ySizing: 'fill', isDraggable: true },
pluginId: 'timeseries', pluginId: 'timeseries',
title: 'Fill height', title: 'Dragabble and resizable',
}), }),
new VizPanel({ }),
placement: { ySizing: 'fill', isDraggable: true }, new SceneGridItem({
x: 12,
y: 0,
width: 12,
height: 10,
isResizable: false,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries', pluginId: 'timeseries',
title: 'Fill height', title: 'Draggable only',
}), }),
], }),
}), new SceneGridItem({
], x: 6,
y: 11,
width: 12,
height: 10,
isResizable: false,
isDraggable: true,
body: new SceneFlexLayout({
direction: 'column',
children: [
new SceneFlexItem({
ySizing: 'fill',
body: new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
}),
new SceneFlexItem({
ySizing: 'fill',
body: new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
}),
],
}),
}),
],
}),
}), }),
], ],
}), }),

View File

@ -1,4 +1,11 @@
import { VizPanel, SceneGridRow, SceneTimePicker, SceneGridLayout, SceneTimeRange } from '@grafana/scenes'; import {
VizPanel,
SceneGridRow,
SceneTimePicker,
SceneGridLayout,
SceneTimeRange,
SceneGridItem,
} from '@grafana/scenes';
import { TestDataQueryType } from 'app/plugins/datasource/testdata/dataquery.gen'; import { TestDataQueryType } from 'app/plugins/datasource/testdata/dataquery.gen';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -16,19 +23,33 @@ export function getGridWithMultipleData(): DashboardScene {
title: 'Row A - has its own query', title: 'Row A - has its own query',
key: 'Row A', key: 'Row A',
isCollapsed: true, isCollapsed: true,
placement: { y: 0 }, y: 0,
children: [ children: [
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 0,
title: 'Row A Child1', y: 1,
key: 'Row A Child1', width: 12,
placement: { x: 0, y: 1, width: 12, height: 5, isResizable: true, isDraggable: true }, height: 5,
isResizable: true,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child1',
key: 'Row A Child1',
}),
}), }),
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 0,
title: 'Row A Child2', y: 5,
key: 'Row A Child2', width: 6,
placement: { x: 0, y: 5, width: 6, height: 5, isResizable: true, isDraggable: true }, height: 5,
isResizable: true,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child2',
key: 'Row A Child2',
}),
}), }),
], ],
}), }),
@ -36,49 +57,63 @@ export function getGridWithMultipleData(): DashboardScene {
title: 'Row B - uses global query', title: 'Row B - uses global query',
key: 'Row B', key: 'Row B',
isCollapsed: true, isCollapsed: true,
placement: { y: 1 }, y: 1,
children: [ children: [
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 0,
title: 'Row B Child1', y: 2,
key: 'Row B Child1', width: 12,
placement: { x: 0, y: 2, width: 12, height: 5, isResizable: false, isDraggable: true }, height: 5,
isResizable: false,
isDraggable: true,
body: new VizPanel({
pluginId: 'timeseries',
title: 'Row B Child1',
key: 'Row B Child1',
}),
}), }),
new VizPanel({ new SceneGridItem({
$data: getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 }), x: 0,
pluginId: 'timeseries', y: 7,
title: 'Row B Child2 with data', width: 6,
key: 'Row B Child2', height: 5,
placement: { x: 0, y: 7, width: 6, height: 5, isResizable: false, isDraggable: true }, isResizable: false,
isDraggable: true,
body: new VizPanel({
$data: getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 }),
pluginId: 'timeseries',
title: 'Row B Child2 with data',
key: 'Row B Child2',
}),
}), }),
], ],
}), }),
new VizPanel({ new SceneGridItem({
$data: getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 }), x: 0,
pluginId: 'timeseries', y: 12,
title: 'Outsider, has its own query', width: 6,
key: 'Outsider-own-query', height: 10,
placement: { isResizable: true,
x: 0, isDraggable: true,
y: 12, body: new VizPanel({
width: 6, $data: getQueryRunnerWithRandomWalkQuery({ seriesCount: 10 }),
height: 10, pluginId: 'timeseries',
isResizable: true, title: 'Outsider, has its own query',
isDraggable: true, key: 'Outsider-own-query',
}, }),
}), }),
new VizPanel({ new SceneGridItem({
pluginId: 'timeseries', x: 6,
title: 'Outsider, uses global query', y: 12,
key: 'Outsider-global-query', width: 12,
placement: { height: 10,
x: 6, isResizable: true,
y: 12, isDraggable: true,
width: 12, body: new VizPanel({
height: 10, pluginId: 'timeseries',
isResizable: true, title: 'Outsider, uses global query',
isDraggable: true, key: 'Outsider-global-query',
}, }),
}), }),
], ],
}), }),

View File

@ -1,71 +0,0 @@
import { VizPanel, SceneGridLayout, SceneGridRow, SceneTimePicker, SceneTimeRange } from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene';
import { getQueryRunnerWithRandomWalkQuery } from './queries';
export function getGridWithRowLayoutTest(): DashboardScene {
return new DashboardScene({
title: 'Grid with row layout test',
body: new SceneGridLayout({
children: [
new SceneGridRow({
title: 'Row A',
key: 'Row A',
isCollapsed: true,
placement: { y: 0 },
children: [
new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child1',
key: 'Row A Child1',
placement: { x: 0, y: 1, width: 12, height: 5, isResizable: true, isDraggable: true },
}),
new VizPanel({
pluginId: 'timeseries',
title: 'Row A Child2',
key: 'Row A Child2',
placement: { x: 0, y: 5, width: 6, height: 5, isResizable: true, isDraggable: true },
}),
],
}),
new SceneGridRow({
title: 'Row B',
key: 'Row B',
isCollapsed: true,
placement: { y: 1 },
children: [
new VizPanel({
pluginId: 'timeseries',
title: 'Row B Child1',
key: 'Row B Child1',
placement: { x: 0, y: 2, width: 12, height: 5, isResizable: false, isDraggable: true },
}),
new VizPanel({
pluginId: 'timeseries',
title: 'Row B Child2',
key: 'Row B Child2',
placement: { x: 0, y: 7, width: 6, height: 5, isResizable: false, isDraggable: true },
}),
],
}),
new VizPanel({
pluginId: 'timeseries',
title: 'Outsider',
key: 'Outsider',
placement: {
x: 2,
y: 12,
width: 12,
height: 10,
isResizable: true,
isDraggable: true,
},
}),
],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
}

View File

@ -1,91 +0,0 @@
import {
VizPanel,
SceneGridRow,
SceneTimePicker,
SceneFlexLayout,
SceneGridLayout,
SceneTimeRange,
} from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene';
import { getQueryRunnerWithRandomWalkQuery } from './queries';
export function getGridWithRowsTest(): DashboardScene {
const panel = new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
});
const row1 = new SceneGridRow({
title: 'Collapsible/draggable row with flex layout',
placement: { x: 0, y: 0, height: 10 },
children: [
new SceneFlexLayout({
direction: 'row',
children: [
new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
],
}),
],
});
const cell1 = new VizPanel({
placement: {
x: 0,
y: 10,
width: 12,
height: 20,
},
pluginId: 'timeseries',
title: 'Cell 1',
});
const cell2 = new VizPanel({
placement: { x: 12, y: 20, width: 12, height: 10, isResizable: false, isDraggable: false },
pluginId: 'timeseries',
title: 'No resize/no drag',
});
const row2 = new SceneGridRow({
placement: { x: 12, y: 10, height: 10, width: 12 },
title: 'Row with a nested flex layout',
children: [
new SceneFlexLayout({
children: [
new SceneFlexLayout({
direction: 'column',
children: [panel, panel],
}),
new SceneFlexLayout({
direction: 'column',
children: [panel, panel],
}),
],
}),
],
});
const scene = new DashboardScene({
title: 'Grid rows test',
body: new SceneGridLayout({
children: [cell1, cell2, row1, row2],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
return scene;
}

View File

@ -1,12 +1,8 @@
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
import { getFlexLayoutTest, getRepeaterSceneWithFlexWrap, getScenePanelRepeaterTest } from './demo';
import { getGridLayoutTest } from './grid';
import { getGridWithMultipleTimeRanges } from './gridMultiTimeRange'; import { getGridWithMultipleTimeRanges } from './gridMultiTimeRange';
import { getMultipleGridLayoutTest } from './gridMultiple'; import { getMultipleGridLayoutTest } from './gridMultiple';
import { getGridWithMultipleData } from './gridWithMultipleData'; import { getGridWithMultipleData } from './gridWithMultipleData';
import { getGridWithRowLayoutTest } from './gridWithRow';
import { getNestedScene } from './nested';
import { getQueryVariableDemo } from './queryVariableDemo'; import { getQueryVariableDemo } from './queryVariableDemo';
import { getSceneWithRows } from './sceneWithRows'; import { getSceneWithRows } from './sceneWithRows';
import { getTransformationsDemo } from './transformations'; import { getTransformationsDemo } from './transformations';
@ -18,13 +14,7 @@ interface SceneDef {
} }
export function getScenes(): SceneDef[] { export function getScenes(): SceneDef[] {
return [ return [
{ title: 'Flex layout test', getScene: getFlexLayoutTest },
{ title: 'Panel repeater test', getScene: getScenePanelRepeaterTest },
{ title: 'Panel repeater test flex wrap', getScene: getRepeaterSceneWithFlexWrap },
{ title: 'Nested Scene demo', getScene: getNestedScene },
{ title: 'Scene with rows', getScene: getSceneWithRows }, { title: 'Scene with rows', getScene: getSceneWithRows },
{ title: 'Grid layout test', getScene: getGridLayoutTest },
{ title: 'Grid with row layout test', getScene: getGridWithRowLayoutTest },
{ title: 'Grid with rows and different queries', getScene: getGridWithMultipleData }, { title: 'Grid with rows and different queries', getScene: getGridWithMultipleData },
{ title: 'Grid with rows and different queries and time ranges', getScene: getGridWithMultipleTimeRanges }, { title: 'Grid with rows and different queries and time ranges', getScene: getGridWithMultipleTimeRanges },
{ title: 'Multiple grid layouts test', getScene: getMultipleGridLayoutTest }, { title: 'Multiple grid layouts test', getScene: getMultipleGridLayoutTest },

View File

@ -1,48 +0,0 @@
import { VizPanel, NestedScene, SceneTimePicker, SceneFlexLayout, SceneTimeRange } from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene';
import { getQueryRunnerWithRandomWalkQuery } from './queries';
export function getNestedScene(): DashboardScene {
return new DashboardScene({
title: 'Nested Scene demo',
body: new SceneFlexLayout({
direction: 'column',
children: [
new VizPanel({
key: '3',
pluginId: 'timeseries',
title: 'Panel 3',
}),
getInnerScene('Inner scene'),
],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
}
export function getInnerScene(title: string) {
const scene = new NestedScene({
title: title,
canRemove: true,
canCollapse: true,
body: new SceneFlexLayout({
direction: 'row',
children: [
new VizPanel({
key: '3',
pluginId: 'timeseries',
title: 'Data',
}),
],
}),
$timeRange: new SceneTimeRange(),
$data: getQueryRunnerWithRandomWalkQuery(),
actions: [new SceneTimePicker({})],
});
return scene;
}

View File

@ -9,6 +9,7 @@ import {
CustomVariable, CustomVariable,
DataSourceVariable, DataSourceVariable,
QueryVariable, QueryVariable,
SceneFlexItem,
} from '@grafana/scenes'; } from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -49,15 +50,13 @@ export function getQueryVariableDemo(): DashboardScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new SceneFlexLayout({ new SceneFlexItem({
children: [ width: '40%',
new SceneCanvasText({ body: new SceneCanvasText({
placement: { width: '40%' }, text: 'metric: ${metric}',
text: 'metric: ${metric}', fontSize: 20,
fontSize: 20, align: 'center',
align: 'center', }),
}),
],
}), }),
], ],
}), }),

View File

@ -1,4 +1,11 @@
import { VizPanel, NestedScene, SceneTimePicker, SceneFlexLayout, SceneTimeRange } from '@grafana/scenes'; import {
VizPanel,
NestedScene,
SceneTimePicker,
SceneFlexLayout,
SceneTimeRange,
SceneFlexItem,
} from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -13,35 +20,42 @@ export function getSceneWithRows(): DashboardScene {
new NestedScene({ new NestedScene({
title: 'Overview', title: 'Overview',
canCollapse: true, canCollapse: true,
// size: { ySizing: 'content', xSizing: 'fill' },
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new VizPanel({ new SceneFlexItem({
pluginId: 'timeseries', body: new VizPanel({
title: 'Fill height', pluginId: 'timeseries',
title: 'Fill height',
}),
}), }),
new VizPanel({
pluginId: 'timeseries', new SceneFlexItem({
title: 'Fill height', body: new VizPanel({
pluginId: 'timeseries',
title: 'Fill height',
}),
}), }),
], ],
}), }),
}), }),
new NestedScene({ new NestedScene({
title: 'More server details', title: 'More server details',
// size: { ySizing: 'content', xSizing: 'fill' },
canCollapse: true, canCollapse: true,
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new VizPanel({ new SceneFlexItem({
pluginId: 'timeseries', body: new VizPanel({
title: 'Fill height', pluginId: 'timeseries',
title: 'Fill height',
}),
}), }),
new VizPanel({ new SceneFlexItem({
pluginId: 'timeseries', body: new VizPanel({
title: 'Fill height', pluginId: 'timeseries',
title: 'Fill height',
}),
}), }),
], ],
}), }),

View File

@ -1,4 +1,11 @@
import { SceneTimePicker, SceneFlexLayout, VizPanel, SceneDataTransformer, SceneTimeRange } from '@grafana/scenes'; import {
SceneTimePicker,
SceneFlexLayout,
VizPanel,
SceneDataTransformer,
SceneTimeRange,
SceneFlexItem,
} from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -10,50 +17,59 @@ export function getTransformationsDemo(): DashboardScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new SceneFlexLayout({ new SceneFlexItem({
direction: 'column', body: new SceneFlexLayout({
children: [ direction: 'column',
new SceneFlexLayout({ children: [
direction: 'row', new SceneFlexItem({
children: [ body: new SceneFlexLayout({
new VizPanel({ direction: 'row',
pluginId: 'timeseries', children: [
title: 'Source data (global query', new SceneFlexItem({
body: new VizPanel({
pluginId: 'timeseries',
title: 'Source data (global query',
}),
}),
new SceneFlexItem({
body: new VizPanel({
pluginId: 'stat',
title: 'Transformed data',
$data: new SceneDataTransformer({
transformations: [
{
id: 'reduce',
options: {
reducers: ['last', 'mean'],
},
},
],
}),
}),
}),
],
}), }),
new VizPanel({ }),
pluginId: 'stat', new SceneFlexItem({
title: 'Transformed data', body: new VizPanel({
$data: new SceneDataTransformer({ $data: new SceneDataTransformer({
$data: getQueryRunnerWithRandomWalkQuery(),
transformations: [ transformations: [
{ {
id: 'reduce', id: 'reduce',
options: { options: {
reducers: ['last', 'mean'], reducers: ['mean'],
}, },
}, },
], ],
}), }),
pluginId: 'stat',
title: 'Query with predefined transformations',
}), }),
],
}),
new VizPanel({
$data: new SceneDataTransformer({
$data: getQueryRunnerWithRandomWalkQuery(),
transformations: [
{
id: 'reduce',
options: {
reducers: ['mean'],
},
},
],
}), }),
],
pluginId: 'stat', }),
title: 'Query with predefined transformations',
}),
],
}), }),
], ],
}), }),

View File

@ -11,6 +11,7 @@ import {
TestVariable, TestVariable,
NestedScene, NestedScene,
TextBoxVariable, TextBoxVariable,
SceneFlexItem,
} from '@grafana/scenes'; } from '@grafana/scenes';
import { DashboardScene } from '../dashboard/DashboardScene'; import { DashboardScene } from '../dashboard/DashboardScene';
@ -65,48 +66,62 @@ export function getVariablesDemo(): DashboardScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new SceneFlexLayout({ new SceneFlexItem({
direction: 'column', body: new SceneFlexLayout({
children: [ direction: 'column',
new SceneFlexLayout({ children: [
children: [ new SceneFlexItem({
new VizPanel({ body: new SceneFlexLayout({
pluginId: 'timeseries', children: [
title: 'handler: $handler', new SceneFlexItem({
$data: getQueryRunnerWithRandomWalkQuery({ body: new VizPanel({
alias: 'handler: $handler', pluginId: 'timeseries',
}), title: 'handler: $handler',
}), $data: getQueryRunnerWithRandomWalkQuery({
new SceneCanvasText({ alias: 'handler: $handler',
text: 'Text: ${textbox}', }),
fontSize: 20, }),
align: 'center',
}),
new SceneCanvasText({
placement: { width: '40%' },
text: 'server: ${server} pod:${pod}',
fontSize: 20,
align: 'center',
}),
],
}),
new NestedScene({
title: 'Collapsable inner scene',
canCollapse: true,
body: new SceneFlexLayout({
direction: 'row',
children: [
new VizPanel({
pluginId: 'timeseries',
title: 'handler: $handler',
$data: getQueryRunnerWithRandomWalkQuery({
alias: 'handler: $handler',
}), }),
}), new SceneFlexItem({
], body: new SceneCanvasText({
text: 'Text: ${textbox}',
fontSize: 20,
align: 'center',
}),
}),
new SceneFlexItem({
width: '40%',
body: new SceneCanvasText({
text: 'server: ${server} pod:${pod}',
fontSize: 20,
align: 'center',
}),
}),
],
}),
}), }),
}), new SceneFlexItem({
], body: new NestedScene({
title: 'Collapsable inner scene',
canCollapse: true,
body: new SceneFlexLayout({
direction: 'row',
children: [
new SceneFlexItem({
body: new VizPanel({
pluginId: 'timeseries',
title: 'handler: $handler',
$data: getQueryRunnerWithRandomWalkQuery({
alias: 'handler: $handler',
}),
}),
}),
],
}),
}),
}),
],
}),
}), }),
], ],
}), }),
@ -158,22 +173,22 @@ export function getVariablesDemoWithAll(): DashboardScene {
body: new SceneFlexLayout({ body: new SceneFlexLayout({
direction: 'row', direction: 'row',
children: [ children: [
new SceneFlexLayout({ new SceneFlexItem({
children: [ body: new VizPanel({
new VizPanel({ pluginId: 'timeseries',
pluginId: 'timeseries', title: 'handler: $handler',
title: 'handler: $handler', $data: getQueryRunnerWithRandomWalkQuery({
$data: getQueryRunnerWithRandomWalkQuery({ alias: 'handler: $handler',
alias: 'handler: $handler',
}),
}), }),
new SceneCanvasText({ }),
placement: { width: '40%' }, }),
text: 'server: ${server} pod:${pod}', new SceneFlexItem({
fontSize: 20, width: '40%',
align: 'center', body: new SceneCanvasText({
}), text: 'server: ${server} pod:${pod}',
], fontSize: 20,
align: 'center',
}),
}), }),
], ],
}), }),

View File

@ -1,4 +1,5 @@
import { formatRegistry, FormatRegistryID } from '@grafana/scenes'; import { formatRegistry } from '@grafana/scenes';
import { VariableFormatID } from '@grafana/schema';
import { isAdHoc } from '../variables/guard'; import { isAdHoc } from '../variables/guard';
@ -12,7 +13,7 @@ export function formatVariableValue(value: any, format?: any, variable?: any, te
return ''; return '';
} }
if (isAdHoc(variable) && format !== FormatRegistryID.queryParam) { if (isAdHoc(variable) && format !== VariableFormatID.QueryParam) {
return ''; return '';
} }
@ -26,7 +27,7 @@ export function formatVariableValue(value: any, format?: any, variable?: any, te
} }
if (!format) { if (!format) {
format = FormatRegistryID.glob; format = VariableFormatID.Glob;
} }
// some formats have arguments that come after ':' character // some formats have arguments that come after ':' character
@ -42,7 +43,7 @@ export function formatVariableValue(value: any, format?: any, variable?: any, te
if (!formatItem) { if (!formatItem) {
console.error(`Variable format ${format} not found. Using glob format as fallback.`); console.error(`Variable format ${format} not found. Using glob format as fallback.`);
formatItem = formatRegistry.get(FormatRegistryID.glob); formatItem = formatRegistry.get(VariableFormatID.Glob);
} }
const formatVariable = getVariableWrapper(variable, value, text ?? value); const formatVariable = getVariableWrapper(variable, value, text ?? value);

View File

@ -1,6 +1,7 @@
import { dateTime, TimeRange } from '@grafana/data'; import { dateTime, TimeRange } from '@grafana/data';
import { setDataSourceSrv, VariableInterpolation } from '@grafana/runtime'; import { setDataSourceSrv, VariableInterpolation } from '@grafana/runtime';
import { FormatRegistryID, TestVariable } from '@grafana/scenes'; import { TestVariable } from '@grafana/scenes';
import { VariableFormatID } from '@grafana/schema';
import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput'; import { silenceConsoleOutput } from '../../../test/core/utils/silenceConsoleOutput';
import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv'; import { initTemplateSrv } from '../../../test/helpers/initTemplateSrv';
@ -697,9 +698,9 @@ describe('templateSrv', () => {
}); });
it(`should not be handled by any registry items except for queryparam`, () => { it(`should not be handled by any registry items except for queryparam`, () => {
const registryItems = Object.values(FormatRegistryID); const registryItems = Object.values(VariableFormatID);
for (const registryItem of registryItems) { for (const registryItem of registryItems) {
if (registryItem === FormatRegistryID.queryParam) { if (registryItem === VariableFormatID.QueryParam) {
continue; continue;
} }

View File

@ -15,7 +15,8 @@ import {
TemplateSrv as BaseTemplateSrv, TemplateSrv as BaseTemplateSrv,
VariableInterpolation, VariableInterpolation,
} from '@grafana/runtime'; } from '@grafana/runtime';
import { sceneGraph, FormatRegistryID, VariableCustomFormatterFn } from '@grafana/scenes'; import { sceneGraph, VariableCustomFormatterFn } from '@grafana/scenes';
import { VariableFormatID } from '@grafana/schema';
import { variableAdapters } from '../variables/adapters'; import { variableAdapters } from '../variables/adapters';
import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/constants'; import { ALL_VARIABLE_TEXT, ALL_VARIABLE_VALUE } from '../variables/constants';
@ -290,7 +291,7 @@ export class TemplateSrv implements BaseTemplateSrv {
return match; return match;
} }
if (format === FormatRegistryID.queryParam || isAdHoc(variable)) { if (format === VariableFormatID.QueryParam || isAdHoc(variable)) {
const value = variableAdapters.get(variable.type).getValueForUrl(variable); const value = variableAdapters.get(variable.type).getValueForUrl(variable);
const text = isAdHoc(variable) ? variable.id : variable.current.text; const text = isAdHoc(variable) ? variable.id : variable.current.text;
@ -309,7 +310,7 @@ export class TemplateSrv implements BaseTemplateSrv {
value = this.getAllValue(variable); value = this.getAllValue(variable);
text = ALL_VARIABLE_TEXT; text = ALL_VARIABLE_TEXT;
// skip formatting of custom all values unless format set to text or percentencode // skip formatting of custom all values unless format set to text or percentencode
if (variable.allValue && format !== FormatRegistryID.text && format !== FormatRegistryID.percentEncode) { if (variable.allValue && format !== VariableFormatID.Text && format !== VariableFormatID.PercentEncode) {
return this.replace(value); return this.replace(value);
} }
} }

View File

@ -1,6 +1,6 @@
import { ScopedVars } from '@grafana/data'; import { ScopedVars } from '@grafana/data';
import { TemplateSrv } from '@grafana/runtime'; import { TemplateSrv } from '@grafana/runtime';
import { FormatRegistryID } from '@grafana/scenes'; import { VariableFormatID } from '@grafana/schema';
import { applyQueryDefaults } from 'app/features/plugins/sql/defaults'; import { applyQueryDefaults } from 'app/features/plugins/sql/defaults';
import { SQLQuery, SqlQueryModel } from 'app/features/plugins/sql/types'; import { SQLQuery, SqlQueryModel } from 'app/features/plugins/sql/types';
@ -16,7 +16,7 @@ export class PostgresQueryModel implements SqlQueryModel {
} }
interpolate() { interpolate() {
return this.templateSrv?.replace(this.target.rawSql, this.scopedVars, FormatRegistryID.sqlString) || ''; return this.templateSrv?.replace(this.target.rawSql, this.scopedVars, VariableFormatID.SQLString) || '';
} }
quoteLiteral(value: string) { quoteLiteral(value: string) {

View File

@ -3326,9 +3326,9 @@ __metadata:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"@grafana/scenes@npm:^0.0.28": "@grafana/scenes@npm:^0.2.0":
version: 0.0.28 version: 0.2.0
resolution: "@grafana/scenes@npm:0.0.28" resolution: "@grafana/scenes@npm:0.2.0"
dependencies: dependencies:
"@grafana/e2e-selectors": ^9.4.3 "@grafana/e2e-selectors": ^9.4.3
"@grafana/experimental": 1.0.1 "@grafana/experimental": 1.0.1
@ -3336,7 +3336,7 @@ __metadata:
react-use: 17.4.0 react-use: 17.4.0
react-virtualized-auto-sizer: 1.0.7 react-virtualized-auto-sizer: 1.0.7
uuid: ^9.0.0 uuid: ^9.0.0
checksum: 0cfcfda325f42c1aee571e32411514954d5a14ac7b40102f33c1c52bd39e65766c3081e634de303379dccd363f78ed4ce022ac71a4d6b7ab3658f18ac81163e7 checksum: a04fe353eec8f048de7c51079e7f7bef461b372c3c086d5ff3be46fc0e70a21e907272f0ed05a41633847a3736c5e65e441ffa20b2c18eedea813decf3eef636
languageName: node languageName: node
linkType: hard linkType: hard
@ -20110,7 +20110,7 @@ __metadata:
"@grafana/lezer-logql": 0.1.2 "@grafana/lezer-logql": 0.1.2
"@grafana/monaco-logql": ^0.0.7 "@grafana/monaco-logql": ^0.0.7
"@grafana/runtime": "workspace:*" "@grafana/runtime": "workspace:*"
"@grafana/scenes": ^0.0.28 "@grafana/scenes": ^0.2.0
"@grafana/schema": "workspace:*" "@grafana/schema": "workspace:*"
"@grafana/toolkit": "workspace:*" "@grafana/toolkit": "workspace:*"
"@grafana/tsconfig": ^1.2.0-rc1 "@grafana/tsconfig": ^1.2.0-rc1