diff --git a/.betterer.results b/.betterer.results
index 976a2137c61..7b7375fa9b9 100644
--- a/.betterer.results
+++ b/.betterer.results
@@ -1606,7 +1606,8 @@ exports[`better eslint`] = {
[0, 0, 0, "Unexpected any. Specify a different type.", "0"]
],
"public/app/features/dashboard-scene/settings/variables/utils.ts:5381": [
- [0, 0, 0, "Unexpected any. Specify a different type.", "0"]
+ [0, 0, 0, "Do not use any type assertions.", "0"],
+ [0, 0, 0, "Unexpected any. Specify a different type.", "1"]
],
"public/app/features/dashboard-scene/settings/version-history/RevertDashboardModal.tsx:5381": [
[0, 0, 0, "No untranslated strings. Wrap text with ", "0"]
diff --git a/package.json b/package.json
index e5bd0bfb49a..9f91adb3250 100644
--- a/package.json
+++ b/package.json
@@ -275,8 +275,8 @@
"@grafana/prometheus": "workspace:*",
"@grafana/runtime": "workspace:*",
"@grafana/saga-icons": "workspace:*",
- "@grafana/scenes": "^6.7.0",
- "@grafana/scenes-react": "^6.7.0",
+ "@grafana/scenes": "^6.8.1",
+ "@grafana/scenes-react": "^6.8.1",
"@grafana/schema": "workspace:*",
"@grafana/sql": "workspace:*",
"@grafana/ui": "workspace:*",
diff --git a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx
index c03102bf873..a667b877357 100644
--- a/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx
+++ b/public/app/features/dashboard-scene/edit-pane/DashboardEditPane.tsx
@@ -132,13 +132,7 @@ export class DashboardEditPane extends SceneObjectBase {
const { selection, contextItems: selected } = elementSelection.getStateWithValue(id, obj, !!multi);
- this.setState({
- selection: new ElementSelection(selection),
- selectionContext: {
- ...this.state.selectionContext,
- selected,
- },
- });
+ this.updateSelection(new ElementSelection(selection), selected);
}
private removeMultiSelectedObject(id: string) {
@@ -153,13 +147,17 @@ export class DashboardEditPane extends SceneObjectBase {
return;
}
- this.setState({
- selection: new ElementSelection([...entries]),
- selectionContext: {
- ...this.state.selectionContext,
- selected,
- },
- });
+ this.updateSelection(new ElementSelection([...entries]), selected);
+ }
+
+ private updateSelection(selection: ElementSelection | undefined, selected: ElementSelectionContextItem[]) {
+ // onBlur events are not fired on unmount and some edit pane inputs have important onBlur events
+ // This make sure they fire before unmounting
+ if (document.activeElement instanceof HTMLElement) {
+ document.activeElement.blur();
+ }
+
+ this.setState({ selection, selectionContext: { ...this.state.selectionContext, selected } });
}
public clearSelection() {
@@ -167,13 +165,7 @@ export class DashboardEditPane extends SceneObjectBase {
return;
}
- this.setState({
- selection: undefined,
- selectionContext: {
- ...this.state.selectionContext,
- selected: [],
- },
- });
+ this.updateSelection(undefined, []);
}
private newObjectAddedToCanvas(obj: SceneObject) {
diff --git a/public/app/features/dashboard-scene/scene/VariableControls.tsx b/public/app/features/dashboard-scene/scene/VariableControls.tsx
index ee425f28519..2f32bc8ee67 100644
--- a/public/app/features/dashboard-scene/scene/VariableControls.tsx
+++ b/public/app/features/dashboard-scene/scene/VariableControls.tsx
@@ -33,6 +33,17 @@ export function VariableValueSelectWrapper({ variable }: VariableSelectProps) {
}
const onPointerDown = (evt: React.PointerEvent) => {
+ if (!isSelectable) {
+ return;
+ }
+
+ // Ignore click if it's inside the value control
+ if (evt.target instanceof Element && !evt.target.closest(`label`)) {
+ // Prevent clearing selection when clicking inside value
+ evt.stopPropagation();
+ return;
+ }
+
if (isSelectable && onSelect) {
evt.stopPropagation();
onSelect(evt);
diff --git a/public/app/features/dashboard-scene/serialization/custom-variables/SnapshotVariable.tsx b/public/app/features/dashboard-scene/serialization/custom-variables/SnapshotVariable.tsx
index 3a84ade2759..5c198abec0d 100644
--- a/public/app/features/dashboard-scene/serialization/custom-variables/SnapshotVariable.tsx
+++ b/public/app/features/dashboard-scene/serialization/custom-variables/SnapshotVariable.tsx
@@ -7,7 +7,7 @@ import {
ValidateAndUpdateResult,
VariableDependencyConfig,
VariableValueOption,
- renderSelectForVariable,
+ MultiOrSingleValueSelect,
sceneGraph,
VariableGetOptionsArgs,
} from '@grafana/scenes';
@@ -64,7 +64,7 @@ export class SnapshotVariable extends MultiValueVariable
}
public static Component = ({ model }: SceneComponentProps>) => {
- return renderSelectForVariable(model);
+ return ;
};
// we will always preserve the current value and text for snapshots
private _updateValueGivenNewOptions(options: VariableValueOption[]) {
diff --git a/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx b/public/app/features/dashboard-scene/settings/variables/VariableEditableElement.tsx
index 7c0da2add37..b8d2ee6f281 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 { SceneVariable, SceneVariableSet } from '@grafana/scenes';
-import { Combobox, Input, TextArea, Stack, Button, Field } from '@grafana/ui';
+import { MultiValueVariable, SceneVariable, SceneVariableSet } from '@grafana/scenes';
+import { Input, TextArea, Button, Field, Box } 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';
@@ -13,7 +13,9 @@ import { useEditPaneInputAutoFocus } from '../../scene/layouts-shared/utils';
import { BulkActionElement } from '../../scene/types/BulkActionElement';
import { EditableDashboardElement, EditableDashboardElementInfo } from '../../scene/types/EditableDashboardElement';
import { VariableHideSelect } from '../../settings/variables/components/VariableHideSelect';
-import { getVariableTypeSelectOptions, validateVariableName } from '../../settings/variables/utils';
+import { getEditableVariableDefinition, validateVariableName } from '../../settings/variables/utils';
+
+import { useVariableSelectionOptionsCategory } from './useVariableSelectionOptionsCategory';
export class VariableEditableElement implements EditableDashboardElement, BulkActionElement {
public readonly isEditableDashboardElement = true;
@@ -22,8 +24,10 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc
public constructor(public variable: SceneVariable) {}
public getEditableElementInfo(): EditableDashboardElementInfo {
+ const variableEditorDef = getEditableVariableDefinition(this.variable.state.type);
+
return {
- typeName: t('dashboard.edit-pane.elements.variable', 'Variable'),
+ typeName: t('dashboard.edit-pane.elements.variable', '{{type}} variable', { type: variableEditorDef.name }),
icon: 'dollar-alt',
instanceName: this.variable.state.name,
isHidden: this.variable.state.hide === VariableHide.hideVariable,
@@ -33,8 +37,8 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc
public useEditPaneOptions(isNewElement: boolean): OptionsPaneCategoryDescriptor[] {
const variable = this.variable;
- const options = useMemo(() => {
- return new OptionsPaneCategoryDescriptor({ title: '', id: 'panel-options' })
+ const basicOptions = useMemo(() => {
+ return new OptionsPaneCategoryDescriptor({ title: '', id: 'variable-options' })
.addItem(
new OptionsPaneItemDescriptor({
title: '',
@@ -44,17 +48,14 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc
)
.addItem(
new OptionsPaneItemDescriptor({
- title: t('dashboard-scene.variable-editor-form.label', 'Label'),
- description: t(
- 'dashboard-scene.variable-editor-form.description-optional-display-name',
- 'Optional display name'
- ),
+ title: t('dashboard.edit-pane.variable.label', 'Label'),
+ description: t('dashboard.edit-pane.variable.label-description', 'Optional display name'),
render: () => ,
})
)
.addItem(
new OptionsPaneItemDescriptor({
- title: t('dashboard-scene.variable-editor-form.description', 'Description'),
+ title: t('dashboard.edit-pane.variable.description', 'Description'),
render: () => ,
})
)
@@ -64,16 +65,18 @@ export class VariableEditableElement implements EditableDashboardElement, BulkAc
skipField: true,
render: () => ,
})
- )
- .addItem(
- new OptionsPaneItemDescriptor({
- title: t('dashboard-scene.variable-editor-form.type', 'Type'),
- render: () => ,
- })
);
}, [variable, isNewElement]);
- return [options];
+ const categories = [basicOptions];
+ const typeCategory = useVariableTypeCategory(variable);
+ categories.push(typeCategory);
+
+ if (variable instanceof MultiValueVariable) {
+ categories.push(useVariableSelectionOptionsCategory(variable));
+ }
+
+ return categories;
}
public onDelete() {
@@ -126,7 +129,7 @@ function VariableNameInput({ variable, isNewElement }: { variable: SceneVariable
};
return (
-
+
);
@@ -144,7 +147,7 @@ function VariableDescriptionTextArea({ variable }: VariableInputProps) {