From 85a0a47efca26f8787bab5d34002ce32f4b987d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Wed, 23 Apr 2025 11:10:09 +0200 Subject: [PATCH] Dashboard: Fixes outline for repeated rows (#104283) * Dashboard: Fixes outline for repeated rows * Update * make i18n-extract --------- Co-authored-by: oscarkilhed --- .../dashboard-scene/edit-pane/shared.ts | 7 ++- .../LocalVariableEditableElement.tsx | 57 +++++++++++++++++++ .../variables/VariableEditableElement.tsx | 48 +++++++++++++++- .../variables/VariableSetEditableElement.tsx | 14 +++-- .../editors/SystemVariableEditor.tsx | 28 +++++++++ public/locales/en-US/grafana.json | 1 + 6 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 public/app/features/dashboard-scene/settings/variables/LocalVariableEditableElement.tsx create mode 100644 public/app/features/dashboard-scene/settings/variables/editors/SystemVariableEditor.tsx diff --git a/public/app/features/dashboard-scene/edit-pane/shared.ts b/public/app/features/dashboard-scene/edit-pane/shared.ts index a53b35208b6..dac06f09cdd 100644 --- a/public/app/features/dashboard-scene/edit-pane/shared.ts +++ b/public/app/features/dashboard-scene/edit-pane/shared.ts @@ -1,11 +1,12 @@ import { useSessionStorage } from 'react-use'; import { BusEventWithPayload } from '@grafana/data'; -import { SceneGridRow, SceneObject, SceneVariableSet, VizPanel } from '@grafana/scenes'; +import { LocalValueVariable, SceneGridRow, SceneObject, SceneVariableSet, VizPanel } from '@grafana/scenes'; import { DashboardScene } from '../scene/DashboardScene'; import { SceneGridRowEditableElement } from '../scene/layout-default/SceneGridRowEditableElement'; import { EditableDashboardElement, isEditableDashboardElement } from '../scene/types/EditableDashboardElement'; +import { LocalVariableEditableElement } from '../settings/variables/LocalVariableEditableElement'; import { VariableEditableElement } from '../settings/variables/VariableEditableElement'; import { VariableSetEditableElement } from '../settings/variables/VariableSetEditableElement'; import { isSceneVariable } from '../settings/variables/utils'; @@ -42,6 +43,10 @@ export function getEditableElementFor(sceneObj: SceneObject | undefined): Editab return new VariableSetEditableElement(sceneObj); } + if (sceneObj instanceof LocalValueVariable) { + return new LocalVariableEditableElement(sceneObj); + } + if (isSceneVariable(sceneObj)) { return new VariableEditableElement(sceneObj); } diff --git a/public/app/features/dashboard-scene/settings/variables/LocalVariableEditableElement.tsx b/public/app/features/dashboard-scene/settings/variables/LocalVariableEditableElement.tsx new file mode 100644 index 00000000000..d5bb9103893 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/LocalVariableEditableElement.tsx @@ -0,0 +1,57 @@ +import { useMemo } from 'react'; + +import { LocalValueVariable } from '@grafana/scenes'; +import { Box, Stack } from '@grafana/ui'; +import { t } from 'app/core/internationalization'; +import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; +import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; + +import { EditableDashboardElement, EditableDashboardElementInfo } from '../../scene/types/EditableDashboardElement'; + +export class LocalVariableEditableElement implements EditableDashboardElement { + public readonly isEditableDashboardElement = true; + + public constructor(public variable: LocalValueVariable) {} + + public getEditableElementInfo(): EditableDashboardElementInfo { + return { + typeName: t('dashboard.edit-pane.elements.local-variable', 'Local variable'), + icon: 'dollar-alt', + instanceName: ` $${this.variable.state.name} = ${this.variable.getValueText!()}`, + isHidden: true, + }; + } + + public useEditPaneOptions(): OptionsPaneCategoryDescriptor[] { + const variable = this.variable; + + return useMemo(() => { + const category = new OptionsPaneCategoryDescriptor({ + title: '', + id: 'local-variable-options', + }); + + category.addItem( + new OptionsPaneItemDescriptor({ + title: '', + skipField: true, + render: () => { + return ( + + + + ${variable.state.name} + = + {variable.getValueText()} + + + + ); + }, + }) + ); + + return [category]; + }, [variable]); + } +} diff --git a/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx b/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx index b8d2ee6f281..213557fc8c4 100644 --- a/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx +++ b/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx @@ -2,8 +2,8 @@ import { FormEvent, useMemo, useState } from 'react'; import { VariableHide } from '@grafana/data'; import { locationService } from '@grafana/runtime'; -import { MultiValueVariable, SceneVariable, SceneVariableSet } from '@grafana/scenes'; -import { Input, TextArea, Button, Field, Box } from '@grafana/ui'; +import { LocalValueVariable, MultiValueVariable, SceneVariable, SceneVariableSet } from '@grafana/scenes'; +import { Input, TextArea, Button, Field, Box, Stack } from '@grafana/ui'; import { t, Trans } from 'app/core/internationalization'; import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneCategoryDescriptor'; import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; @@ -24,6 +24,15 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc public constructor(public variable: SceneVariable) {} public getEditableElementInfo(): EditableDashboardElementInfo { + if (this.variable instanceof LocalValueVariable) { + return { + typeName: t('dashboard.edit-pane.elements.local-variable', 'Local variable'), + icon: 'dollar-alt', + instanceName: this.variable.state.name, + isHidden: true, + }; + } + const variableEditorDef = getEditableVariableDefinition(this.variable.state.type); return { @@ -37,6 +46,10 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc public useEditPaneOptions(isNewElement: boolean): OptionsPaneCategoryDescriptor[] { const variable = this.variable; + if (variable instanceof LocalValueVariable) { + return useLocalVariableOptions(variable); + } + const basicOptions = useMemo(() => { return new OptionsPaneCategoryDescriptor({ title: '', id: 'variable-options' }) .addItem( @@ -220,3 +233,34 @@ function OpenOldVariableEditButton({ variable }: VariableInputProps) { ); } + +function useLocalVariableOptions(variable: LocalValueVariable): OptionsPaneCategoryDescriptor[] { + return useMemo(() => { + const category = new OptionsPaneCategoryDescriptor({ + title: '', + id: 'local-variable-options', + }); + + category.addItem( + new OptionsPaneItemDescriptor({ + title: '', + skipField: true, + render: () => { + return ( + + + + ${variable.state.name} + = + {variable.getValueText()} + + + + ); + }, + }) + ); + + return [category]; + }, [variable]); +} diff --git a/public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx b/public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx index a1e4047901f..442f7c58b47 100644 --- a/public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx +++ b/public/app/features/dashboard-scene/settings/variables/VariableSetEditableElement.tsx @@ -10,6 +10,7 @@ import { OptionsPaneCategoryDescriptor } from 'app/features/dashboard/components import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; import { NewObjectAddedToCanvasEvent } from '../../edit-pane/shared'; +import { DashboardScene } from '../../scene/DashboardScene'; import { EditableDashboardElement, EditableDashboardElementInfo } from '../../scene/types/EditableDashboardElement'; import { getDashboardSceneFor } from '../../utils/utils'; @@ -51,6 +52,7 @@ function VariableList({ set }: { set: SceneVariableSet }) { const { variables } = set.useState(); const styles = useStyles2(getStyles); const [isAdding, setIsAdding] = useToggle(false); + const canAdd = set.parent instanceof DashboardScene; const onEditVariable = (variable: SceneVariable) => { const { editPane } = getDashboardSceneFor(set).state; @@ -83,11 +85,13 @@ function VariableList({ set }: { set: SceneVariableSet }) { ))} - - - + {canAdd && ( + + + + )} ); } diff --git a/public/app/features/dashboard-scene/settings/variables/editors/SystemVariableEditor.tsx b/public/app/features/dashboard-scene/settings/variables/editors/SystemVariableEditor.tsx new file mode 100644 index 00000000000..d7a55ae5dad --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/editors/SystemVariableEditor.tsx @@ -0,0 +1,28 @@ +import { SceneVariable, LocalValueVariable } from '@grafana/scenes'; +import { Stack } from '@grafana/ui'; +import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; + +export function getSystemVariableOptions(variable: SceneVariable): OptionsPaneItemDescriptor[] { + if (!(variable instanceof LocalValueVariable)) { + return []; + } + + return [ + new OptionsPaneItemDescriptor({ + title: '', + render: () => { + return ( + + + + ${variable.state.name} + = + ${variable.getValueText()} + + + + ); + }, + }), + ]; +} diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 01564808222..f56e7ceb411 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -3173,6 +3173,7 @@ "edit-pane": { "elements": { "dashboard": "Dashboard", + "local-variable": "Local variable", "multiple-elements": "Multiple elements", "multiple-elements-delete-text": "Are you sure you want to delete these elements?", "multiple-panels": "Multiple panels",