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 { NavIndex } from '@grafana/data';
|
||||||
import { config, locationService } from '@grafana/runtime';
|
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 { PanelDataPane } from './PanelDataPane/PanelDataPane';
|
||||||
import { PanelEditorRenderer } from './PanelEditorRenderer';
|
import { PanelEditorRenderer } from './PanelEditorRenderer';
|
||||||
import { PanelOptionsPane } from './PanelOptionsPane';
|
import { PanelOptionsPane } from './PanelOptionsPane';
|
||||||
import { VizPanelManager } from './VizPanelManager';
|
import { VizPanelManager, VizPanelManagerState } from './VizPanelManager';
|
||||||
|
|
||||||
export interface PanelEditorState extends SceneObjectState {
|
export interface PanelEditorState extends SceneObjectState {
|
||||||
isDirty?: boolean;
|
isDirty?: boolean;
|
||||||
@@ -20,12 +21,21 @@ export interface PanelEditorState extends SceneObjectState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
||||||
|
private _initialRepeatOptions: Pick<VizPanelManagerState, 'repeat' | 'repeatDirection' | 'maxPerRow'> = {};
|
||||||
static Component = PanelEditorRenderer;
|
static Component = PanelEditorRenderer;
|
||||||
|
|
||||||
private _discardChanges = false;
|
private _discardChanges = false;
|
||||||
|
|
||||||
public constructor(state: PanelEditorState) {
|
public constructor(state: PanelEditorState) {
|
||||||
super(state);
|
super(state);
|
||||||
|
|
||||||
|
const { repeat, repeatDirection, maxPerRow } = state.vizManager.state;
|
||||||
|
this._initialRepeatOptions = {
|
||||||
|
repeat,
|
||||||
|
repeatDirection,
|
||||||
|
maxPerRow,
|
||||||
|
};
|
||||||
|
|
||||||
this.addActivationHandler(this._activationHandler.bind(this));
|
this.addActivationHandler(this._activationHandler.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +98,104 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
|
|||||||
dashboard.onEnterEditMode();
|
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,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,11 +15,12 @@ interface Props {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const PanelOptions = React.memo<Props>(({ vizManager, searchQuery, listMode }) => {
|
export const PanelOptions = React.memo<Props>(({ vizManager, searchQuery, listMode }) => {
|
||||||
const { panel } = vizManager.state;
|
const { panel } = vizManager.useState();
|
||||||
const { data } = sceneGraph.getData(panel).useState();
|
const { data } = sceneGraph.getData(panel).useState();
|
||||||
const { options, fieldConfig } = panel.useState();
|
const { options, fieldConfig } = panel.useState();
|
||||||
|
|
||||||
const panelFrameOptions = useMemo(() => getPanelFrameCategory2(panel), [panel]);
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
const panelFrameOptions = useMemo(() => getPanelFrameCategory2(vizManager), [vizManager, panel]);
|
||||||
|
|
||||||
const visualizationOptions = useMemo(() => {
|
const visualizationOptions = useMemo(() => {
|
||||||
const plugin = panel.getPlugin();
|
const plugin = panel.getPlugin();
|
||||||
|
|||||||
@@ -35,16 +35,20 @@ import { updateQueries } from 'app/features/query/state/updateQueries';
|
|||||||
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
import { GrafanaQuery } from 'app/plugins/datasource/grafana/types';
|
||||||
import { QueryGroupOptions } from 'app/types';
|
import { QueryGroupOptions } from 'app/types';
|
||||||
|
|
||||||
|
import { PanelRepeaterGridItem, RepeatDirection } from '../scene/PanelRepeaterGridItem';
|
||||||
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
|
import { PanelTimeRange, PanelTimeRangeState } from '../scene/PanelTimeRange';
|
||||||
import { gridItemToPanel } from '../serialization/transformSceneToSaveModel';
|
import { gridItemToPanel } from '../serialization/transformSceneToSaveModel';
|
||||||
import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
import { getDashboardSceneFor, getPanelIdForVizPanel, getQueryRunnerFor } from '../utils/utils';
|
||||||
|
|
||||||
interface VizPanelManagerState extends SceneObjectState {
|
export interface VizPanelManagerState extends SceneObjectState {
|
||||||
panel: VizPanel;
|
panel: VizPanel;
|
||||||
sourcePanel: SceneObjectRef<VizPanel>;
|
sourcePanel: SceneObjectRef<VizPanel>;
|
||||||
datasource?: DataSourceApi;
|
datasource?: DataSourceApi;
|
||||||
dsSettings?: DataSourceInstanceSettings;
|
dsSettings?: DataSourceInstanceSettings;
|
||||||
tableView?: VizPanel;
|
tableView?: VizPanel;
|
||||||
|
repeat?: string;
|
||||||
|
repeatDirection?: RepeatDirection;
|
||||||
|
maxPerRow?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DisplayMode {
|
export enum DisplayMode {
|
||||||
@@ -70,10 +74,17 @@ export class VizPanelManager extends SceneObjectBase<VizPanelManagerState> {
|
|||||||
* live on the VizPanelManager level instead of the VizPanel level
|
* live on the VizPanelManager level instead of the VizPanel level
|
||||||
*/
|
*/
|
||||||
public static createFor(sourcePanel: VizPanel) {
|
public static createFor(sourcePanel: VizPanel) {
|
||||||
|
let repeatOptions: Pick<VizPanelManagerState, 'repeat' | 'repeatDirection' | 'maxPerRow'> = {};
|
||||||
|
if (sourcePanel.parent instanceof PanelRepeaterGridItem) {
|
||||||
|
const { variableName: repeat, repeatDirection, maxPerRow } = sourcePanel.parent.state;
|
||||||
|
repeatOptions = { repeat, repeatDirection, maxPerRow };
|
||||||
|
}
|
||||||
|
|
||||||
return new VizPanelManager({
|
return new VizPanelManager({
|
||||||
panel: sourcePanel.clone({ $data: undefined }),
|
panel: sourcePanel.clone({ $data: undefined }),
|
||||||
$data: sourcePanel.state.$data?.clone(),
|
$data: sourcePanel.state.$data?.clone(),
|
||||||
sourcePanel: sourcePanel.getRef(),
|
sourcePanel: sourcePanel.getRef(),
|
||||||
|
...repeatOptions,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ interface PanelRepeaterGridItemState extends SceneGridItemStateLike {
|
|||||||
repeatedPanels?: VizPanel[];
|
repeatedPanels?: VizPanel[];
|
||||||
variableName: string;
|
variableName: string;
|
||||||
itemHeight?: number;
|
itemHeight?: number;
|
||||||
repeatDirection?: RepeatDirection | string;
|
repeatDirection?: RepeatDirection;
|
||||||
maxPerRow?: number;
|
maxPerRow?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -462,7 +462,8 @@ export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (panel.repeat) {
|
if (panel.repeat) {
|
||||||
const repeatDirection = panel.repeatDirection ?? 'h';
|
const repeatDirection = panel.repeatDirection === 'h' ? 'h' : 'v';
|
||||||
|
|
||||||
return new PanelRepeaterGridItem({
|
return new PanelRepeaterGridItem({
|
||||||
key: `grid-item-${panel.id}`,
|
key: `grid-item-${panel.id}`,
|
||||||
x: panel.gridPos.x,
|
x: panel.gridPos.x,
|
||||||
@@ -473,7 +474,7 @@ export function buildGridItemForPanel(panel: PanelModel): SceneGridItemLike {
|
|||||||
source: new VizPanel(vizPanelState),
|
source: new VizPanel(vizPanelState),
|
||||||
variableName: panel.repeat,
|
variableName: panel.repeat,
|
||||||
repeatedPanels: [],
|
repeatedPanels: [],
|
||||||
repeatDirection: panel.repeatDirection,
|
repeatDirection: repeatDirection,
|
||||||
maxPerRow: panel.maxPerRow,
|
maxPerRow: panel.maxPerRow,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
|
import { SelectableValue } from '@grafana/data';
|
||||||
import { config } from '@grafana/runtime';
|
import { config } from '@grafana/runtime';
|
||||||
import { VizPanel } from '@grafana/scenes';
|
|
||||||
import { DataLinksInlineEditor, Input, RadioButtonGroup, Select, Switch, TextArea } from '@grafana/ui';
|
import { DataLinksInlineEditor, Input, RadioButtonGroup, Select, Switch, TextArea } from '@grafana/ui';
|
||||||
|
import { VizPanelManager, VizPanelManagerState } from 'app/features/dashboard-scene/panel-edit/VizPanelManager';
|
||||||
import { VizPanelLinks } from 'app/features/dashboard-scene/scene/PanelLinks';
|
import { VizPanelLinks } from 'app/features/dashboard-scene/scene/PanelLinks';
|
||||||
import { dashboardSceneGraph } from 'app/features/dashboard-scene/utils/dashboardSceneGraph';
|
import { dashboardSceneGraph } from 'app/features/dashboard-scene/utils/dashboardSceneGraph';
|
||||||
import { getPanelLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
|
import { getPanelLinksVariableSuggestions } from 'app/features/panel/panellinks/link_srv';
|
||||||
|
|
||||||
import { GenAIPanelDescriptionButton } from '../GenAI/GenAIPanelDescriptionButton';
|
import { GenAIPanelDescriptionButton } from '../GenAI/GenAIPanelDescriptionButton';
|
||||||
import { GenAIPanelTitleButton } from '../GenAI/GenAIPanelTitleButton';
|
import { GenAIPanelTitleButton } from '../GenAI/GenAIPanelTitleButton';
|
||||||
import { RepeatRowSelect } from '../RepeatRowSelect/RepeatRowSelect';
|
import { RepeatRowSelect, RepeatRowSelect2 } from '../RepeatRowSelect/RepeatRowSelect';
|
||||||
|
|
||||||
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
|
import { OptionsPaneCategoryDescriptor } from './OptionsPaneCategoryDescriptor';
|
||||||
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
import { OptionsPaneItemDescriptor } from './OptionsPaneItemDescriptor';
|
||||||
@@ -175,7 +176,8 @@ export function getPanelFrameCategory(props: OptionPaneRenderProps): OptionsPane
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPanelFrameCategory2(panel: VizPanel): OptionsPaneCategoryDescriptor {
|
export function getPanelFrameCategory2(panelManager: VizPanelManager): OptionsPaneCategoryDescriptor {
|
||||||
|
const { panel } = panelManager.state;
|
||||||
const descriptor = new OptionsPaneCategoryDescriptor({
|
const descriptor = new OptionsPaneCategoryDescriptor({
|
||||||
title: 'Panel options',
|
title: 'Panel options',
|
||||||
id: 'Panel options',
|
id: 'Panel options',
|
||||||
@@ -252,69 +254,72 @@ export function getPanelFrameCategory2(panel: VizPanel): OptionsPaneCategoryDesc
|
|||||||
render: () => <ScenePanelLinksEditor panelLinks={panelLinksObject} />,
|
render: () => <ScenePanelLinksEditor panelLinks={panelLinksObject} />,
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
);
|
)
|
||||||
//
|
.addCategory(
|
||||||
// .addCategory(
|
new OptionsPaneCategoryDescriptor({
|
||||||
// new OptionsPaneCategoryDescriptor({
|
title: 'Repeat options',
|
||||||
// title: 'Repeat options',
|
id: 'Repeat options',
|
||||||
// id: 'Repeat options',
|
isOpenDefault: false,
|
||||||
// isOpenDefault: false,
|
})
|
||||||
// })
|
.addItem(
|
||||||
// .addItem(
|
new OptionsPaneItemDescriptor({
|
||||||
// new OptionsPaneItemDescriptor({
|
title: 'Repeat by variable',
|
||||||
// title: 'Repeat by variable',
|
description:
|
||||||
// description:
|
'Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.',
|
||||||
// 'Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.',
|
render: function renderRepeatOptions() {
|
||||||
// render: function renderRepeatOptions() {
|
return (
|
||||||
// return (
|
<RepeatRowSelect2
|
||||||
// <RepeatRowSelect
|
id="repeat-by-variable-select"
|
||||||
// id="repeat-by-variable-select"
|
panelManager={panelManager}
|
||||||
// repeat={panel.repeat}
|
onChange={(value?: string) => {
|
||||||
// onChange={(value?: string) => {
|
const stateUpdate: Partial<VizPanelManagerState> = { repeat: value };
|
||||||
// onPanelConfigChange('repeat', value);
|
if (value && !panelManager.state.repeatDirection) {
|
||||||
// }}
|
stateUpdate.repeatDirection = 'h';
|
||||||
// />
|
}
|
||||||
// );
|
panelManager.setState(stateUpdate);
|
||||||
// },
|
}}
|
||||||
// })
|
/>
|
||||||
// )
|
);
|
||||||
// .addItem(
|
},
|
||||||
// new OptionsPaneItemDescriptor({
|
})
|
||||||
// title: 'Repeat direction',
|
)
|
||||||
// showIf: () => !!panel.repeat,
|
.addItem(
|
||||||
// render: function renderRepeatOptions() {
|
new OptionsPaneItemDescriptor({
|
||||||
// const directionOptions = [
|
title: 'Repeat direction',
|
||||||
// { label: 'Horizontal', value: 'h' },
|
showIf: () => !!panelManager.state.repeat,
|
||||||
// { label: 'Vertical', value: 'v' },
|
render: function renderRepeatOptions() {
|
||||||
// ];
|
const directionOptions: Array<SelectableValue<'h' | 'v'>> = [
|
||||||
|
{ label: 'Horizontal', value: 'h' },
|
||||||
|
{ label: 'Vertical', value: 'v' },
|
||||||
|
];
|
||||||
|
|
||||||
// return (
|
return (
|
||||||
// <RadioButtonGroup
|
<RadioButtonGroup
|
||||||
// options={directionOptions}
|
options={directionOptions}
|
||||||
// value={panel.repeatDirection || 'h'}
|
value={panelManager.state.repeatDirection ?? 'h'}
|
||||||
// onChange={(value) => onPanelConfigChange('repeatDirection', value)}
|
onChange={(value) => panelManager.setState({ repeatDirection: value })}
|
||||||
// />
|
/>
|
||||||
// );
|
);
|
||||||
// },
|
},
|
||||||
// })
|
})
|
||||||
// )
|
)
|
||||||
// .addItem(
|
.addItem(
|
||||||
// new OptionsPaneItemDescriptor({
|
new OptionsPaneItemDescriptor({
|
||||||
// title: 'Max per row',
|
title: 'Max per row',
|
||||||
// showIf: () => Boolean(panel.repeat && panel.repeatDirection === 'h'),
|
showIf: () => Boolean(panelManager.state.repeat && panelManager.state.repeatDirection === 'h'),
|
||||||
// render: function renderOption() {
|
render: function renderOption() {
|
||||||
// const maxPerRowOptions = [2, 3, 4, 6, 8, 12].map((value) => ({ label: value.toString(), value }));
|
const maxPerRowOptions = [2, 3, 4, 6, 8, 12].map((value) => ({ label: value.toString(), value }));
|
||||||
// return (
|
return (
|
||||||
// <Select
|
<Select
|
||||||
// options={maxPerRowOptions}
|
options={maxPerRowOptions}
|
||||||
// value={panel.maxPerRow}
|
value={panelManager.state.maxPerRow}
|
||||||
// onChange={(value) => onPanelConfigChange('maxPerRow', value.value)}
|
onChange={(value) => panelManager.setState({ maxPerRow: value.value })}
|
||||||
// />
|
/>
|
||||||
// );
|
);
|
||||||
// },
|
},
|
||||||
// })
|
})
|
||||||
// )
|
)
|
||||||
// );
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ScenePanelLinksEditorProps {
|
interface ScenePanelLinksEditorProps {
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
import React, { useCallback, useMemo } from 'react';
|
import React, { useCallback, useMemo } from 'react';
|
||||||
|
|
||||||
import { SelectableValue } from '@grafana/data';
|
import { SelectableValue } from '@grafana/data';
|
||||||
|
import { sceneGraph } from '@grafana/scenes';
|
||||||
import { Select } from '@grafana/ui';
|
import { Select } from '@grafana/ui';
|
||||||
|
import { VizPanelManager } from 'app/features/dashboard-scene/panel-edit/VizPanelManager';
|
||||||
import { useSelector } from 'app/types';
|
import { useSelector } from 'app/types';
|
||||||
|
|
||||||
import { getLastKey, getVariablesByKey } from '../../../variables/state/selectors';
|
import { getLastKey, getVariablesByKey } from '../../../variables/state/selectors';
|
||||||
@@ -41,3 +43,40 @@ export const RepeatRowSelect = ({ repeat, onChange, id }: Props) => {
|
|||||||
|
|
||||||
return <Select inputId={id} value={repeat} onChange={onSelectChange} options={variableOptions} />;
|
return <Select inputId={id} value={repeat} onChange={onSelectChange} options={variableOptions} />;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface Props2 {
|
||||||
|
panelManager: VizPanelManager;
|
||||||
|
id?: string;
|
||||||
|
onChange: (name?: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const RepeatRowSelect2 = ({ panelManager, id, onChange }: Props2) => {
|
||||||
|
const { panel, repeat } = panelManager.useState();
|
||||||
|
const sceneVars = useMemo(() => sceneGraph.getVariables(panel), [panel]);
|
||||||
|
const variables = sceneVars.useState().variables;
|
||||||
|
|
||||||
|
const variableOptions = useMemo(() => {
|
||||||
|
const options: Array<SelectableValue<string | null>> = variables.map((item) => ({
|
||||||
|
label: item.state.name,
|
||||||
|
value: item.state.name,
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (options.length === 0) {
|
||||||
|
options.unshift({
|
||||||
|
label: 'No template variables found',
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
options.unshift({
|
||||||
|
label: 'Disable repeating',
|
||||||
|
value: null,
|
||||||
|
});
|
||||||
|
|
||||||
|
return options;
|
||||||
|
}, [variables]);
|
||||||
|
|
||||||
|
const onSelectChange = useCallback((option: SelectableValue<string | null>) => onChange(option.value!), [onChange]);
|
||||||
|
|
||||||
|
return <Select inputId={id} value={repeat} onChange={onSelectChange} options={variableOptions} />;
|
||||||
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user