From 3658b1fce7f5c3aaa4cd335fbbcf63b77bb3dcd4 Mon Sep 17 00:00:00 2001 From: Levente Balogh Date: Thu, 9 Oct 2025 14:08:55 +0200 Subject: [PATCH] Dashboards: Add a new variable type called "Switch" (#111366) * feat: add schema changes for a switch type of dashboard variable * fix: generated go * feat: add support for a switch type of dashboard variable * chore: update `@grafana/scenes` to a canary version * feat: add variable editor for the switch variable * fix: remove unnecessary jest config change * chore: remove commented out code --- .../kinds/v2beta1/dashboard_spec.cue | 20 +- .../dashboard/v0alpha1/dashboard_kind.cue | 3 +- .../apis/dashboard/v1beta1/dashboard_kind.cue | 3 +- .../apis/dashboard/v2beta1/dashboard_spec.cue | 20 +- .../dashboard/v2beta1/dashboard_spec_gen.go | 70 +++- .../dashboard/v2beta1/zz_generated.openapi.go | 352 +++++++++++------- ...enerated.openapi_violation_exceptions.list | 17 +- kinds/dashboard/dashboard_kind.cue | 3 +- package.json | 4 +- packages/grafana-data/src/index.ts | 1 + .../grafana-data/src/types/templateVars.ts | 7 +- .../src/selectors/pages.ts | 11 + .../raw/dashboard/x/dashboard_types.gen.ts | 3 +- .../dashboard/v2beta1/types.spec.gen.ts | 32 +- pkg/kinds/dashboard/dashboard_spec_gen.go | 2 + .../scene/VariableControls.tsx | 28 ++ .../sceneVariablesSetToVariables.test.ts | 258 +++++++++++++ .../sceneVariablesSetToVariables.ts | 50 +++ .../transformSaveModelSchemaV2ToScene.ts | 20 +- .../transformSceneToSaveModelSchemaV2.ts | 2 + .../components/SwitchVariableForm.test.tsx | 131 +++++++ .../components/SwitchVariableForm.tsx | 145 ++++++++ .../editors/SwitchVariableEditor.test.tsx | 155 ++++++++ .../editors/SwitchVariableEditor.tsx | 55 +++ .../settings/variables/utils.test.ts | 4 +- .../settings/variables/utils.ts | 17 +- .../dashboard-scene/utils/variables.test.ts | 162 ++++++++ .../dashboard-scene/utils/variables.ts | 27 ++ .../dashboard-scene/v2schema/test-helpers.ts | 8 +- public/app/features/variables/guard.test.ts | 2 + .../variables/state/__tests__/fixtures.ts | 26 ++ public/locales/en-US/grafana.json | 13 + yarn.lock | 22 +- 33 files changed, 1502 insertions(+), 171 deletions(-) create mode 100644 public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.test.tsx create mode 100644 public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.tsx create mode 100644 public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.test.tsx create mode 100644 public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.tsx diff --git a/apps/dashboard/kinds/v2beta1/dashboard_spec.cue b/apps/dashboard/kinds/v2beta1/dashboard_spec.cue index fe9d13de67f..f0278fc431c 100644 --- a/apps/dashboard/kinds/v2beta1/dashboard_spec.cue +++ b/apps/dashboard/kinds/v2beta1/dashboard_spec.cue @@ -710,9 +710,9 @@ VariableCustomFormatterFn: { // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" + "system" | "snapshot" | "switch" -VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind +VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind // Sort variable options // Accepted values are: @@ -904,6 +904,22 @@ CustomVariableKind: { spec: CustomVariableSpec } +SwitchVariableSpec: { + name: string | *"" + current: string | *"false" + enabledValue: string | *"true" + disabledValue: string | *"false" + label?: string + hide: VariableHide + skipUrlSync: bool | *false + description?: string +} + +SwitchVariableKind: { + kind: "SwitchVariable" + spec: SwitchVariableSpec +} + // GroupBy variable specification GroupByVariableSpec: { name: string | *"" diff --git a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue index fb971b2cc3f..526ddba3bfc 100644 --- a/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue +++ b/apps/dashboard/pkg/apis/dashboard/v0alpha1/dashboard_kind.cue @@ -364,8 +364,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue index fb971b2cc3f..526ddba3bfc 100644 --- a/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue +++ b/apps/dashboard/pkg/apis/dashboard/v1beta1/dashboard_kind.cue @@ -364,8 +364,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue index 2c7d74674f2..fb46afb5c76 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec.cue @@ -714,9 +714,9 @@ VariableCustomFormatterFn: { // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" + "system" | "snapshot" | "switch" -VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind +VariableKind: QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind // Sort variable options // Accepted values are: @@ -908,6 +908,22 @@ CustomVariableKind: { spec: CustomVariableSpec } +SwitchVariableSpec: { + name: string | *"" + current: string | *"false" + enabledValue: string | *"true" + disabledValue: string | *"false" + label?: string + hide: VariableHide + skipUrlSync: bool | *false + description?: string +} + +SwitchVariableKind: { + kind: "SwitchVariable" + spec: SwitchVariableSpec +} + // GroupBy variable specification GroupByVariableSpec: { name: string | *"" diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go index d43c7765f16..783d91665a0 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/dashboard_spec_gen.go @@ -1290,11 +1290,11 @@ func NewDashboardTimeRangeOption() *DashboardTimeRangeOption { } // +k8s:openapi-gen=true -type DashboardVariableKind = DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind +type DashboardVariableKind = DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind // NewDashboardVariableKind creates a new DashboardVariableKind object. func NewDashboardVariableKind() *DashboardVariableKind { - return NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind() + return NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind() } // Query variable kind @@ -1815,6 +1815,44 @@ func NewDashboardMetricFindValue() *DashboardMetricFindValue { return &DashboardMetricFindValue{} } +// +k8s:openapi-gen=true +type DashboardSwitchVariableKind struct { + Kind string `json:"kind"` + Spec DashboardSwitchVariableSpec `json:"spec"` +} + +// NewDashboardSwitchVariableKind creates a new DashboardSwitchVariableKind object. +func NewDashboardSwitchVariableKind() *DashboardSwitchVariableKind { + return &DashboardSwitchVariableKind{ + Kind: "SwitchVariable", + Spec: *NewDashboardSwitchVariableSpec(), + } +} + +// +k8s:openapi-gen=true +type DashboardSwitchVariableSpec struct { + Name string `json:"name"` + Current string `json:"current"` + EnabledValue string `json:"enabledValue"` + DisabledValue string `json:"disabledValue"` + Label *string `json:"label,omitempty"` + Hide DashboardVariableHide `json:"hide"` + SkipUrlSync bool `json:"skipUrlSync"` + Description *string `json:"description,omitempty"` +} + +// NewDashboardSwitchVariableSpec creates a new DashboardSwitchVariableSpec object. +func NewDashboardSwitchVariableSpec() *DashboardSwitchVariableSpec { + return &DashboardSwitchVariableSpec{ + Name: "", + Current: "false", + EnabledValue: "true", + DisabledValue: "false", + Hide: DashboardVariableHideDontHide, + SkipUrlSync: false, + } +} + // +k8s:openapi-gen=true type DashboardSpec struct { Annotations []DashboardAnnotationQueryKind `json:"annotations"` @@ -2433,7 +2471,7 @@ func (resource *DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTab } // +k8s:openapi-gen=true -type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind struct { +type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind struct { QueryVariableKind *DashboardQueryVariableKind `json:"QueryVariableKind,omitempty"` TextVariableKind *DashboardTextVariableKind `json:"TextVariableKind,omitempty"` ConstantVariableKind *DashboardConstantVariableKind `json:"ConstantVariableKind,omitempty"` @@ -2442,15 +2480,16 @@ type DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasou CustomVariableKind *DashboardCustomVariableKind `json:"CustomVariableKind,omitempty"` GroupByVariableKind *DashboardGroupByVariableKind `json:"GroupByVariableKind,omitempty"` AdhocVariableKind *DashboardAdhocVariableKind `json:"AdhocVariableKind,omitempty"` + SwitchVariableKind *DashboardSwitchVariableKind `json:"SwitchVariableKind,omitempty"` } -// NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind creates a new DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind object. -func NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind() *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind { - return &DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind{} +// NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind creates a new DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind object. +func NewDashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind() *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind { + return &DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind{} } -// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` as JSON. -func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) MarshalJSON() ([]byte, error) { +// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind` as JSON. +func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind) MarshalJSON() ([]byte, error) { if resource.QueryVariableKind != nil { return json.Marshal(resource.QueryVariableKind) } @@ -2475,12 +2514,15 @@ func (resource DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKin if resource.AdhocVariableKind != nil { return json.Marshal(resource.AdhocVariableKind) } + if resource.SwitchVariableKind != nil { + return json.Marshal(resource.SwitchVariableKind) + } return []byte("null"), nil } -// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind` from JSON. -func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind) UnmarshalJSON(raw []byte) error { +// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind` from JSON. +func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind) UnmarshalJSON(raw []byte) error { if raw == nil { return nil } @@ -2553,6 +2595,14 @@ func (resource *DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKi resource.QueryVariableKind = &dashboardQueryVariableKind return nil + case "SwitchVariable": + var dashboardSwitchVariableKind DashboardSwitchVariableKind + if err := json.Unmarshal(raw, &dashboardSwitchVariableKind); err != nil { + return err + } + + resource.SwitchVariableKind = &dashboardSwitchVariableKind + return nil case "TextVariable": var dashboardTextVariableKind DashboardTextVariableKind if err := json.Unmarshal(raw, &dashboardTextVariableKind); err != nil { diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go index d1429c9ae7f..39e6e37503f 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi.go @@ -14,127 +14,129 @@ import ( func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenAPIDefinition { return map[string]common.OpenAPIDefinition{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationActions": schema_pkg_apis_dashboard_v2beta1_AnnotationActions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationPermission": schema_pkg_apis_dashboard_v2beta1_AnnotationPermission(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.Dashboard": schema_pkg_apis_dashboard_v2beta1_Dashboard(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAccess": schema_pkg_apis_dashboard_v2beta1_DashboardAccess(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAction": schema_pkg_apis_dashboard_v2beta1_DashboardAction(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardActionVariable": schema_pkg_apis_dashboard_v2beta1_DashboardActionVariable(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdHocFilterWithLabels": schema_pkg_apis_dashboard_v2beta1_DashboardAdHocFilterWithLabels(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationPanelFilter": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationPanelFilter(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQuerySpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardClient": schema_pkg_apis_dashboard_v2beta1_DashboardClient(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConversionStatus": schema_pkg_apis_dashboard_v2beta1_DashboardConversionStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink": schema_pkg_apis_dashboard_v2beta1_DashboardDashboardLink(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataLink": schema_pkg_apis_dashboard_v2beta1_DashboardDataLink(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardDataQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataTransformerConfig": schema_pkg_apis_dashboard_v2beta1_DashboardDataTransformerConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDynamicConfigValue": schema_pkg_apis_dashboard_v2beta1_DashboardDynamicConfigValue(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardElementReference": schema_pkg_apis_dashboard_v2beta1_DashboardElementReference(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFetchOptions": schema_pkg_apis_dashboard_v2beta1_DashboardFetchOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldColor": schema_pkg_apis_dashboard_v2beta1_DashboardFieldColor(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfigSource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardInfinityOptions": schema_pkg_apis_dashboard_v2beta1_DashboardInfinityOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardJSONCodec": schema_pkg_apis_dashboard_v2beta1_DashboardJSONCodec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKindSpec": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKindSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelRef": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelRef(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardList": schema_pkg_apis_dashboard_v2beta1_DashboardList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMatcherConfig": schema_pkg_apis_dashboard_v2beta1_DashboardMatcherConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetadata": schema_pkg_apis_dashboard_v2beta1_DashboardMetadata(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetricFindValue": schema_pkg_apis_dashboard_v2beta1_DashboardMetricFindValue(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKindOrLibraryPanelKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQueryKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQuerySpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelSpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryOptionsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryOptionsSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRangeMap": schema_pkg_apis_dashboard_v2beta1_DashboardRangeMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRegexMap": schema_pkg_apis_dashboard_v2beta1_DashboardRegexMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRowRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardSpecialValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStatus": schema_pkg_apis_dashboard_v2beta1_DashboardStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrArrayOfString(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrFloat64": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThreshold": schema_pkg_apis_dashboard_v2beta1_DashboardThreshold(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThresholdsConfig": schema_pkg_apis_dashboard_v2beta1_DashboardThresholdsConfig(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2beta1_DashboardTimeRangeOption(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTimeSettingsSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2beta1_DashboardTransformationKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1ActionStyle": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1ActionStyle(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1AdhocVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1AdhocVariableKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1DataQueryKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1FieldConfigSourceOverrides(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1GroupByVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1GroupByVariableKindDatasource(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RangeMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RangeMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RegexMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RegexMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1SpecialValueMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1SpecialValueMapOptions(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMappingResult": schema_pkg_apis_dashboard_v2beta1_DashboardValueMappingResult(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVariableOption": schema_pkg_apis_dashboard_v2beta1_DashboardVariableOption(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionInfo": schema_pkg_apis_dashboard_v2beta1_DashboardVersionInfo(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionList": schema_pkg_apis_dashboard_v2beta1_DashboardVersionList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigKind": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigKind(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigSpec": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardWithAccessInfo": schema_pkg_apis_dashboard_v2beta1_DashboardWithAccessInfo(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanel": schema_pkg_apis_dashboard_v2beta1_LibraryPanel(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelList": schema_pkg_apis_dashboard_v2beta1_LibraryPanelList(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelSpec": schema_pkg_apis_dashboard_v2beta1_LibraryPanelSpec(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelStatus": schema_pkg_apis_dashboard_v2beta1_LibraryPanelStatus(ref), - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.VersionsQueryOptions": schema_pkg_apis_dashboard_v2beta1_VersionsQueryOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationActions": schema_pkg_apis_dashboard_v2beta1_AnnotationActions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.AnnotationPermission": schema_pkg_apis_dashboard_v2beta1_AnnotationPermission(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.Dashboard": schema_pkg_apis_dashboard_v2beta1_Dashboard(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAccess": schema_pkg_apis_dashboard_v2beta1_DashboardAccess(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAction": schema_pkg_apis_dashboard_v2beta1_DashboardAction(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardActionVariable": schema_pkg_apis_dashboard_v2beta1_DashboardActionVariable(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdHocFilterWithLabels": schema_pkg_apis_dashboard_v2beta1_DashboardAdHocFilterWithLabels(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAdhocVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationPanelFilter": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationPanelFilter(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardAnnotationQuerySpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutItemSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAutoGridRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardAutoGridRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardClient": schema_pkg_apis_dashboard_v2beta1_DashboardClient(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingDataSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingDataSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingGroupSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingTimeRangeSizeSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingTimeRangeSizeSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeRangeSizeKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConditionalRenderingVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConditionalRenderingVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardConstantVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConversionStatus": schema_pkg_apis_dashboard_v2beta1_DashboardConversionStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardCustomVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink": schema_pkg_apis_dashboard_v2beta1_DashboardDashboardLink(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataLink": schema_pkg_apis_dashboard_v2beta1_DashboardDataLink(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardDataQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDataTransformerConfig": schema_pkg_apis_dashboard_v2beta1_DashboardDataTransformerConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardDatasourceVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDynamicConfigValue": schema_pkg_apis_dashboard_v2beta1_DashboardDynamicConfigValue(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardElementReference": schema_pkg_apis_dashboard_v2beta1_DashboardElementReference(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFetchOptions": schema_pkg_apis_dashboard_v2beta1_DashboardFetchOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldColor": schema_pkg_apis_dashboard_v2beta1_DashboardFieldColor(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfig": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardFieldConfigSource": schema_pkg_apis_dashboard_v2beta1_DashboardFieldConfigSource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutItemSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutItemSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrAutoGridLayoutKindOrTabsLayoutKindOrRowsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGridLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardGroupByVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardInfinityOptions": schema_pkg_apis_dashboard_v2beta1_DashboardInfinityOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardIntervalVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardJSONCodec": schema_pkg_apis_dashboard_v2beta1_DashboardJSONCodec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelKindSpec": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelKindSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardLibraryPanelRef": schema_pkg_apis_dashboard_v2beta1_DashboardLibraryPanelRef(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardList": schema_pkg_apis_dashboard_v2beta1_DashboardList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMatcherConfig": schema_pkg_apis_dashboard_v2beta1_DashboardMatcherConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetadata": schema_pkg_apis_dashboard_v2beta1_DashboardMetadata(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardMetricFindValue": schema_pkg_apis_dashboard_v2beta1_DashboardMetricFindValue(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelKindOrLibraryPanelKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQueryKind": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQueryKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelQuerySpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelQuerySpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelSpec": schema_pkg_apis_dashboard_v2beta1_DashboardPanelSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryGroupSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryGroupSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryOptionsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryOptionsSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRangeMap": schema_pkg_apis_dashboard_v2beta1_DashboardRangeMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRegexMap": schema_pkg_apis_dashboard_v2beta1_DashboardRegexMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardRowRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowKind": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutRowSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutRowSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardRowsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardRowsLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardSpecialValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStatus": schema_pkg_apis_dashboard_v2beta1_DashboardStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrArrayOfString": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrArrayOfString(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardStringOrFloat64": schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabRepeatOptions": schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabKind": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTabsLayoutTabSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTabsLayoutTabSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTextVariableSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThreshold": schema_pkg_apis_dashboard_v2beta1_DashboardThreshold(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardThresholdsConfig": schema_pkg_apis_dashboard_v2beta1_DashboardThresholdsConfig(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeRangeOption": schema_pkg_apis_dashboard_v2beta1_DashboardTimeRangeOption(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec": schema_pkg_apis_dashboard_v2beta1_DashboardTimeSettingsSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTransformationKind": schema_pkg_apis_dashboard_v2beta1_DashboardTransformationKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1ActionStyle": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1ActionStyle(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1AdhocVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1AdhocVariableKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1DataQueryKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1DataQueryKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1FieldConfigSourceOverrides": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1FieldConfigSourceOverrides(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1GroupByVariableKindDatasource": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1GroupByVariableKindDatasource(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RangeMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RangeMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1RegexMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1RegexMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardV2beta1SpecialValueMapOptions": schema_pkg_apis_dashboard_v2beta1_DashboardV2beta1SpecialValueMapOptions(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap": schema_pkg_apis_dashboard_v2beta1_DashboardValueMapOrRangeMapOrRegexMapOrSpecialValueMap(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardValueMappingResult": schema_pkg_apis_dashboard_v2beta1_DashboardValueMappingResult(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVariableOption": schema_pkg_apis_dashboard_v2beta1_DashboardVariableOption(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionInfo": schema_pkg_apis_dashboard_v2beta1_DashboardVersionInfo(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVersionList": schema_pkg_apis_dashboard_v2beta1_DashboardVersionList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigKind": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigKind(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardVizConfigSpec": schema_pkg_apis_dashboard_v2beta1_DashboardVizConfigSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardWithAccessInfo": schema_pkg_apis_dashboard_v2beta1_DashboardWithAccessInfo(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanel": schema_pkg_apis_dashboard_v2beta1_LibraryPanel(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelList": schema_pkg_apis_dashboard_v2beta1_LibraryPanelList(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelSpec": schema_pkg_apis_dashboard_v2beta1_LibraryPanelSpec(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.LibraryPanelStatus": schema_pkg_apis_dashboard_v2beta1_LibraryPanelStatus(ref), + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.VersionsQueryOptions": schema_pkg_apis_dashboard_v2beta1_VersionsQueryOptions(ref), } } @@ -3452,7 +3454,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKind(ref common.Ref } } -func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { +func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ SchemaProps: spec.SchemaProps{ @@ -3498,11 +3500,16 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardQueryVariableKindOrTextVariableK Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind"), }, }, + "SwitchVariableKind": { + SchemaProps: spec.SchemaProps{ + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind"), + }, + }, }, }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardConstantVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardCustomVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDatasourceVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGroupByVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardIntervalVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTextVariableKind"}, } } @@ -4054,7 +4061,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref common.ReferenceCallbac Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ SchemaProps: spec.SchemaProps{ - Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind"), + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind"), }, }, }, @@ -4065,7 +4072,7 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardSpec(ref common.ReferenceCallbac }, }, Dependencies: []string{ - "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec"}, + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardAnnotationQueryKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardDashboardLink", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardGridLayoutKindOrRowsLayoutKindOrAutoGridLayoutKindOrTabsLayoutKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardPanelKindOrLibraryPanelKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind", "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardTimeSettingsSpec"}, } } @@ -4174,6 +4181,101 @@ func schema_pkg_apis_dashboard_v2beta1_DashboardStringOrFloat64(ref common.Refer } } +func schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableKind(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec"), + }, + }, + }, + Required: []string{"kind", "spec"}, + }, + }, + Dependencies: []string{ + "github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1.DashboardSwitchVariableSpec"}, + } +} + +func schema_pkg_apis_dashboard_v2beta1_DashboardSwitchVariableSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "current": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "enabledValue": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "disabledValue": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "label": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + "hide": { + SchemaProps: spec.SchemaProps{ + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "skipUrlSync": { + SchemaProps: spec.SchemaProps{ + Default: false, + Type: []string{"boolean"}, + Format: "", + }, + }, + "description": { + SchemaProps: spec.SchemaProps{ + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "current", "enabledValue", "disabledValue", "hide", "skipUrlSync"}, + }, + }, + } +} + func schema_pkg_apis_dashboard_v2beta1_DashboardTabRepeatOptions(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list index b6c9fc53fd2..5a0edf5747d 100644 --- a/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list +++ b/apps/dashboard/pkg/apis/dashboard/v2beta1/zz_generated.openapi_violation_exceptions.list @@ -55,14 +55,15 @@ API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/ap API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardIntervalVariableSpec,AutoMin API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardPanelKindOrLibraryPanelKind,LibraryPanelKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardPanelKindOrLibraryPanelKind,PanelKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,AdhocVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,ConstantVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,CustomVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,DatasourceVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,GroupByVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,IntervalVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,QueryVariableKind -API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKind,TextVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,AdhocVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,ConstantVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,CustomVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,DatasourceVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,GroupByVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,IntervalVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,QueryVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,SwitchVariableKind +API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardQueryVariableKindOrTextVariableKindOrConstantVariableKindOrDatasourceVariableKindOrIntervalVariableKindOrCustomVariableKindOrGroupByVariableKindOrAdhocVariableKindOrSwitchVariableKind,TextVariableKind API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrArrayOfString,ArrayOfString API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrArrayOfString,String API rule violation: names_match,github.com/grafana/grafana/apps/dashboard/pkg/apis/dashboard/v2beta1,DashboardStringOrFloat64,Float64 diff --git a/kinds/dashboard/dashboard_kind.cue b/kinds/dashboard/dashboard_kind.cue index 20571c8211a..13c2b4f25f6 100644 --- a/kinds/dashboard/dashboard_kind.cue +++ b/kinds/dashboard/dashboard_kind.cue @@ -360,8 +360,9 @@ lineage: schemas: [{ // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + // `switch`: Boolean variables rendered as a switch #VariableType: "query" | "adhoc" | "groupby" | "constant" | "datasource" | "interval" | "textbox" | "custom" | - "system" | "snapshot" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) + "system" | "snapshot" | "switch" @cuetsy(kind="type") @grafanamaturity(NeedsExpertReview) // Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. // Continuous color interpolates a color using the percentage of a value relative to min and max. diff --git a/package.json b/package.json index e3614d04384..c33de69bf67 100644 --- a/package.json +++ b/package.json @@ -296,8 +296,8 @@ "@grafana/plugin-ui": "^0.10.10", "@grafana/prometheus": "workspace:*", "@grafana/runtime": "workspace:*", - "@grafana/scenes": "6.38.0", - "@grafana/scenes-react": "6.38.0", + "@grafana/scenes": "6.39.3", + "@grafana/scenes-react": "6.39.3", "@grafana/schema": "workspace:*", "@grafana/sql": "workspace:*", "@grafana/ui": "workspace:*", diff --git a/packages/grafana-data/src/index.ts b/packages/grafana-data/src/index.ts index 269dba30b62..e058612a3c7 100644 --- a/packages/grafana-data/src/index.ts +++ b/packages/grafana-data/src/index.ts @@ -533,6 +533,7 @@ export { type QueryVariableModel, type TextBoxVariableModel, type ConstantVariableModel, + type SwitchVariableModel, type VariableWithMultiSupport, type VariableWithOptions, type DashboardProps, diff --git a/packages/grafana-data/src/types/templateVars.ts b/packages/grafana-data/src/types/templateVars.ts index 347b01b10d1..e6feea4dd3f 100644 --- a/packages/grafana-data/src/types/templateVars.ts +++ b/packages/grafana-data/src/types/templateVars.ts @@ -23,7 +23,8 @@ export type TypedVariableModel = | UserVariableModel | OrgVariableModel | DashboardVariableModel - | SnapshotVariableModel; + | SnapshotVariableModel + | SwitchVariableModel; export enum VariableRefresh { never, // removed from the UI @@ -130,6 +131,10 @@ export interface ConstantVariableModel extends VariableWithOptions { type: 'constant'; } +export interface SwitchVariableModel extends VariableWithOptions { + type: 'switch'; +} + export interface VariableWithMultiSupport extends VariableWithOptions { multi: boolean; includeAll: boolean; diff --git a/packages/grafana-e2e-selectors/src/selectors/pages.ts b/packages/grafana-e2e-selectors/src/selectors/pages.ts index 581a8294d10..b45357f05f7 100644 --- a/packages/grafana-e2e-selectors/src/selectors/pages.ts +++ b/packages/grafana-e2e-selectors/src/selectors/pages.ts @@ -596,6 +596,17 @@ export const versionedPages = { '11.0.0': 'data-testid ad-hoc filters variable mode toggle', }, }, + SwitchVariable: { + valuePairTypeSelect: { + ['12.3.0']: 'data-testid switch variable value pair type select', + }, + enabledValueInput: { + ['12.3.0']: 'data-testid switch variable enabled value input', + }, + disabledValueInput: { + ['12.3.0']: 'data-testid switch variable disabled value input', + }, + }, }, }, }, diff --git a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts index d158d884aa0..b370fc6206c 100644 --- a/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts +++ b/packages/grafana-schema/src/raw/dashboard/x/dashboard_types.gen.ts @@ -454,8 +454,9 @@ export const defaultAction: Partial = { * `textbox`: Display a free text input field with an optional default value. * `custom`: Define the variable options manually using a comma-separated list. * `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables + * `switch`: Boolean variables rendered as a switch */ -export type VariableType = ('query' | 'adhoc' | 'groupby' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system' | 'snapshot'); +export type VariableType = ('query' | 'adhoc' | 'groupby' | 'constant' | 'datasource' | 'interval' | 'textbox' | 'custom' | 'system' | 'snapshot' | 'switch'); /** * Color mode for a field. You can specify a single color, or select a continuous (gradient) color schemes, based on a value. diff --git a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts index 40c2d212d31..aabcbcec235 100644 --- a/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts +++ b/packages/grafana-schema/src/schema/dashboard/v2beta1/types.spec.gen.ts @@ -1052,7 +1052,7 @@ export const defaultTimeRangeOption = (): TimeRangeOption => ({ to: "now", }); -export type VariableKind = QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind; +export type VariableKind = QueryVariableKind | TextVariableKind | ConstantVariableKind | DatasourceVariableKind | IntervalVariableKind | CustomVariableKind | GroupByVariableKind | AdhocVariableKind | SwitchVariableKind; export const defaultVariableKind = (): VariableKind => (defaultQueryVariableKind()); @@ -1444,6 +1444,36 @@ export const defaultMetricFindValue = (): MetricFindValue => ({ text: "", }); +export interface SwitchVariableKind { + kind: "SwitchVariable"; + spec: SwitchVariableSpec; +} + +export const defaultSwitchVariableKind = (): SwitchVariableKind => ({ + kind: "SwitchVariable", + spec: defaultSwitchVariableSpec(), +}); + +export interface SwitchVariableSpec { + name: string; + current: string; + enabledValue: string; + disabledValue: string; + label?: string; + hide: VariableHide; + skipUrlSync: boolean; + description?: string; +} + +export const defaultSwitchVariableSpec = (): SwitchVariableSpec => ({ + name: "", + current: "false", + enabledValue: "true", + disabledValue: "false", + hide: "dontHide", + skipUrlSync: false, +}); + export interface Spec { annotations: AnnotationQueryKind[]; // Configuration of dashboard cursor sync behavior. diff --git a/pkg/kinds/dashboard/dashboard_spec_gen.go b/pkg/kinds/dashboard/dashboard_spec_gen.go index fa72f781f75..75ccc58ce0a 100644 --- a/pkg/kinds/dashboard/dashboard_spec_gen.go +++ b/pkg/kinds/dashboard/dashboard_spec_gen.go @@ -845,6 +845,7 @@ func NewVariableModel() *VariableModel { // `textbox`: Display a free text input field with an optional default value. // `custom`: Define the variable options manually using a comma-separated list. // `system`: Variables defined by Grafana. See: https://grafana.com/docs/grafana/latest/dashboards/variables/add-template-variables/#global-variables +// `switch`: Boolean variables rendered as a switch type VariableType string const ( @@ -858,6 +859,7 @@ const ( VariableTypeCustom VariableType = "custom" VariableTypeSystem VariableType = "system" VariableTypeSnapshot VariableType = "snapshot" + VariableTypeSwitch VariableType = "switch" ) // Determine if the variable shows on dashboard diff --git a/public/app/features/dashboard-scene/scene/VariableControls.tsx b/public/app/features/dashboard-scene/scene/VariableControls.tsx index 45e61146ae1..e285b94e5e1 100644 --- a/public/app/features/dashboard-scene/scene/VariableControls.tsx +++ b/public/app/features/dashboard-scene/scene/VariableControls.tsx @@ -9,6 +9,7 @@ import { SceneVariableState, ControlsLabel, ControlsLayout, + sceneUtils, } from '@grafana/scenes'; import { useElementSelection, useStyles2 } from '@grafana/ui'; @@ -64,6 +65,18 @@ export function VariableValueSelectWrapper({ variable, inMenu }: VariableSelectP } }; + // For switch variables in menu, we want to show the switch on the left and the label on the right + if (inMenu && sceneUtils.isSwitchVariable(variable)) { + return ( +
+
+ +
+ +
+ ); + } + if (inMenu) { return (
@@ -134,6 +147,21 @@ const getStyles = (theme: GrafanaTheme2) => ({ display: 'flex', flexDirection: 'column', }), + switchMenuContainer: css({ + display: 'flex', + alignItems: 'center', + gap: theme.spacing(1), + }), + switchControl: css({ + '& > div': { + border: 'none', + background: 'transparent', + paddingRight: theme.spacing(0.5), + }, + }), + switchLabel: css({ + marginTop: theme.spacing(0.5), + }), labelWrapper: css({ display: 'flex', alignItems: 'center', diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts index e91b28cc646..8772646b496 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.test.ts @@ -21,6 +21,7 @@ import { IntervalVariable, QueryVariable, SceneVariableSet, + SwitchVariable, TextBoxVariable, } from '@grafana/scenes'; import { DataSourceRef, VariableHide, VariableRefresh } from '@grafana/schema'; @@ -877,6 +878,168 @@ describe('sceneVariablesSetToVariables', () => { }); }); + it('should handle SwitchVariable with "true" value', () => { + const variable = new SwitchVariable({ + name: 'test', + label: 'test-label', + description: 'test-desc', + hide: VariableHide.inControlsMenu, + value: 'true', + skipUrlSync: true, + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToVariables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "current": { + "text": "true", + "value": "true", + }, + "description": "test-desc", + "hide": 3, + "label": "test-label", + "name": "test", + "options": [ + { + "text": "true", + "value": "true", + }, + { + "text": "false", + "value": "false", + }, + ], + "skipUrlSync": true, + "type": "switch", +} +`); + }); + + it('should handle SwitchVariable with "false" value', () => { + const variable = new SwitchVariable({ + name: 'test', + label: 'test-label', + description: 'test-desc', + hide: VariableHide.inControlsMenu, + value: 'false', + skipUrlSync: false, + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToVariables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "current": { + "text": "false", + "value": "false", + }, + "description": "test-desc", + "hide": 3, + "label": "test-label", + "name": "test", + "options": [ + { + "text": "true", + "value": "true", + }, + { + "text": "false", + "value": "false", + }, + ], + "type": "switch", +} +`); + }); + + it('should handle SwitchVariable with custom values', () => { + const variable = new SwitchVariable({ + name: 'test', + label: 'test-label', + description: 'test-desc', + hide: VariableHide.inControlsMenu, + value: 'on', + enabledValue: 'on', + disabledValue: 'off', + skipUrlSync: false, + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToVariables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "current": { + "text": "on", + "value": "on", + }, + "description": "test-desc", + "hide": 3, + "label": "test-label", + "name": "test", + "options": [ + { + "text": "on", + "value": "on", + }, + { + "text": "off", + "value": "off", + }, + ], + "type": "switch", +} +`); + }); + + it('should handle SwitchVariable with minimal configuration', () => { + const variable = new SwitchVariable({ + name: 'minimal', + value: 'true', + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToVariables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "current": { + "text": "true", + "value": "true", + }, + "description": undefined, + "label": undefined, + "name": "minimal", + "options": [ + { + "text": "true", + "value": "true", + }, + { + "text": "false", + "value": "false", + }, + ], + "type": "switch", +} +`); + }); + describe('sceneVariablesSetToSchemaV2Variables', () => { it('should handle QueryVariable', () => { const variable = new QueryVariable({ @@ -1455,5 +1618,100 @@ describe('sceneVariablesSetToVariables', () => { expect(() => sceneVariablesSetToSchemaV2Variables(set)).toThrow('Unsupported variable type'); }); }); + + it('should handle SwitchVariable with true value', () => { + const variable = new SwitchVariable({ + name: 'test', + label: 'test-label', + description: 'test-desc', + hide: VariableHide.inControlsMenu, + value: 'true', + skipUrlSync: true, + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToSchemaV2Variables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "kind": "SwitchVariable", + "spec": { + "current": "true", + "description": "test-desc", + "disabledValue": "false", + "enabledValue": "true", + "hide": "inControlsMenu", + "label": "test-label", + "name": "test", + "skipUrlSync": true, + }, +} +`); + }); + + it('should handle SwitchVariable with false value', () => { + const variable = new SwitchVariable({ + name: 'test', + label: 'test-label', + description: 'test-desc', + hide: VariableHide.inControlsMenu, + value: 'false', + skipUrlSync: false, + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToSchemaV2Variables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "kind": "SwitchVariable", + "spec": { + "current": "false", + "description": "test-desc", + "disabledValue": "false", + "enabledValue": "true", + "hide": "inControlsMenu", + "label": "test-label", + "name": "test", + "skipUrlSync": false, + }, +} +`); + }); + + it('should handle SwitchVariable with minimal configuration', () => { + const variable = new SwitchVariable({ + name: 'minimal', + value: 'true', + }); + const set = new SceneVariableSet({ + variables: [variable], + }); + + const result = sceneVariablesSetToSchemaV2Variables(set); + + expect(result).toHaveLength(1); + expect(result[0]).toMatchInlineSnapshot(` +{ + "kind": "SwitchVariable", + "spec": { + "current": "true", + "description": undefined, + "disabledValue": "false", + "enabledValue": "true", + "hide": "dontHide", + "label": undefined, + "name": "minimal", + "skipUrlSync": false, + }, +} +`); + }); }); }); diff --git a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts index 87cde15a7ea..01fe0927619 100644 --- a/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts +++ b/public/app/features/dashboard-scene/serialization/sceneVariablesSetToVariables.ts @@ -26,6 +26,7 @@ import { VariableOption, defaultDataQueryKind, AdHocFilterWithLabels, + SwitchVariableKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2'; import { getDefaultDatasource } from 'app/features/dashboard/api/ResponseTransformers'; @@ -210,6 +211,24 @@ export function sceneVariablesSetToVariables(set: SceneVariables, keepQueryOptio filters: [...validateFiltersOrigin(variable.state.originFilters), ...variable.state.filters], defaultKeys: variable.state.defaultKeys, }); + } else if (sceneUtils.isSwitchVariable(variable)) { + variables.push({ + ...commonProperties, + current: { + value: variable.state.value, + text: variable.state.value, + }, + options: [ + { + value: variable.state.enabledValue, + text: variable.state.enabledValue, + }, + { + value: variable.state.disabledValue, + text: variable.state.disabledValue, + }, + ], + }); } else if (variable.state.type === 'system') { // Not persisted } else { @@ -264,6 +283,7 @@ export function sceneVariablesSetToSchemaV2Variables( | ConstantVariableKind | GroupByVariableKind | AdhocVariableKind + | SwitchVariableKind > { let variables: Array< | QueryVariableKind @@ -274,6 +294,7 @@ export function sceneVariablesSetToSchemaV2Variables( | ConstantVariableKind | GroupByVariableKind | AdhocVariableKind + | SwitchVariableKind > = []; for (const variable of set.state.variables) { @@ -294,6 +315,8 @@ export function sceneVariablesSetToSchemaV2Variables( }; let options: VariableOption[] = []; + + // Query variable if (sceneUtils.isQueryVariable(variable)) { // Not sure if we actually have to still support this option given // that it's not exposed in the UI @@ -355,6 +378,8 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(queryVariable); + + // Custom variable } else if (sceneUtils.isCustomVariable(variable)) { options = variableValueOptionsToVariableOptions(variable.state); const customVariable: CustomVariableKind = { @@ -371,6 +396,8 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(customVariable); + + // Datasource variable } else if (sceneUtils.isDataSourceVariable(variable)) { const datasourceVariable: DatasourceVariableKind = { kind: 'DatasourceVariable', @@ -392,6 +419,8 @@ export function sceneVariablesSetToSchemaV2Variables( } variables.push(datasourceVariable); + + // Constant variable } else if (sceneUtils.isConstantVariable(variable)) { const constantVariable: ConstantVariableKind = { kind: 'ConstantVariable', @@ -407,6 +436,8 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(constantVariable); + + // Interval variable } else if (sceneUtils.isIntervalVariable(variable)) { const intervals = getIntervalsQueryFromNewIntervalModel(variable.state.intervals); const intervalVariable: IntervalVariableKind = { @@ -431,6 +462,8 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(intervalVariable); + + // Textbox variable } else if (sceneUtils.isTextBoxVariable(variable)) { const current = { text: variable.state.value, @@ -447,6 +480,8 @@ export function sceneVariablesSetToSchemaV2Variables( }; variables.push(textBoxVariable); + + // Groupby variable } else if (sceneUtils.isGroupByVariable(variable) && config.featureToggles.groupByVariable) { options = variableValueOptionsToVariableOptions(variable.state); @@ -483,6 +518,8 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(groupVariable); + + // Adhoc variable } else if (sceneUtils.isAdHocVariable(variable)) { const ds = getDataSourceForQuery( variable.state.datasource, @@ -508,6 +545,19 @@ export function sceneVariablesSetToSchemaV2Variables( }, }; variables.push(adhocVariable); + + // Switch variable + } else if (sceneUtils.isSwitchVariable(variable)) { + const switchVariable: SwitchVariableKind = { + kind: 'SwitchVariable', + spec: { + ...commonProperties, + current: variable.state.value, + enabledValue: variable.state.enabledValue, + disabledValue: variable.state.disabledValue, + }, + }; + variables.push(switchVariable); } else if (variable.state.type === 'system') { // Do nothing } else { diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index d352c75a5ec..ad94f404e68 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -16,6 +16,7 @@ import { SceneVariable, SceneVariableSet, ScopesVariable, + SwitchVariable, TextBoxVariable, } from '@grafana/scenes'; import { @@ -34,11 +35,13 @@ import { defaultIntervalVariableKind, defaultQueryVariableKind, defaultTextVariableKind, + defaultSwitchVariableKind, GroupByVariableKind, IntervalVariableKind, LibraryPanelKind, PanelKind, QueryVariableKind, + SwitchVariableKind, TextVariableKind, } from '@grafana/schema/dist/esm/schema/dashboard/v2'; import { DEFAULT_ANNOTATION_COLOR } from '@grafana/ui'; @@ -92,7 +95,8 @@ export type TypedVariableModelV2 = | IntervalVariableKind | CustomVariableKind | GroupByVariableKind - | AdhocVariableKind; + | AdhocVariableKind + | SwitchVariableKind; export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo): DashboardScene { const { spec: dashboard, metadata, apiVersion } = dto; @@ -415,6 +419,15 @@ function createSceneVariableFromVariableModel(variable: TypedVariableModelV2): S // @ts-expect-error defaultOptions: variable.options, }); + } else if (variable.kind === defaultSwitchVariableKind().kind) { + return new SwitchVariable({ + ...commonProperties, + value: variable.spec.current ?? 'false', + enabledValue: variable.spec.enabledValue ?? 'true', + disabledValue: variable.spec.disabledValue ?? 'false', + skipUrlSync: variable.spec.skipUrlSync, + hide: transformVariableHideToEnumV1(variable.spec.hide), + }); } else { throw new Error(`Scenes: Unsupported variable type ${variable.kind}`); } @@ -520,6 +533,11 @@ export function createSnapshotVariable(variable: TypedVariableModelV2): SceneVar value: '', text: '', }; + } else if (variable.kind === 'SwitchVariable') { + current = { + value: variable.spec.current ?? 'false', + text: variable.spec.current ?? 'false', + }; } else { current = { value: variable.spec.current?.value ?? '', diff --git a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts index dd92ca69b00..a1d379d9865 100644 --- a/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts +++ b/public/app/features/dashboard-scene/serialization/transformSceneToSaveModelSchemaV2.ts @@ -44,6 +44,7 @@ import { FieldColor, defaultFieldConfig, defaultDataQueryKind, + SwitchVariableKind, } from '../../../../../packages/grafana-schema/src/schema/dashboard/v2'; import { DashboardDataLayerSet } from '../scene/DashboardDataLayerSet'; import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene'; @@ -411,6 +412,7 @@ function getVariables(oldDash: DashboardSceneState, dsReferencesMapping?: DSRefe | ConstantVariableKind | GroupByVariableKind | AdhocVariableKind + | SwitchVariableKind > = []; if (variablesSet instanceof SceneVariableSet) { diff --git a/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.test.tsx b/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.test.tsx new file mode 100644 index 00000000000..a5561a5ecd6 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.test.tsx @@ -0,0 +1,131 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { selectors } from '@grafana/e2e-selectors'; + +import { SwitchVariableForm } from './SwitchVariableForm'; + +describe('SwitchVariableForm', () => { + const onEnabledValueChange = jest.fn(); + const onDisabledValueChange = jest.fn(); + + const defaultProps = { + enabledValue: 'true', + disabledValue: 'false', + onEnabledValueChange, + onDisabledValueChange, + }; + + function renderForm(props = {}) { + return render(); + } + + beforeEach(() => { + jest.clearAllMocks(); + }); + + it('should render the form', () => { + render(); + + expect(screen.getByText('Switch options')).toBeInTheDocument(); + expect(screen.getByText('Value pair type')).toBeInTheDocument(); + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect) + ).toBeInTheDocument(); + }); + + it('should not show custom inputs for predefined value pair types', () => { + renderForm(); + + expect( + screen.queryByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput) + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput) + ).not.toBeInTheDocument(); + }); + + it('should show custom inputs when value pair type is custom', () => { + renderForm({ + enabledValue: 'on', + disabledValue: 'off', + }); + + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput) + ).toBeInTheDocument(); + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput) + ).toBeInTheDocument(); + }); + + it('should call onEnabledValueChange when enabled value input changes', async () => { + const user = userEvent.setup(); + renderForm({ + enabledValue: '', + disabledValue: 'off', + }); + + const enabledInput = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput + ); + await user.type(enabledInput, 't'); + + expect(onEnabledValueChange).toHaveBeenCalledTimes(1); + expect(onEnabledValueChange).toHaveBeenNthCalledWith(1, 't'); + }); + + it('should call onDisabledValueChange when disabled value input changes', async () => { + const user = userEvent.setup(); + renderForm({ + enabledValue: 'on', + disabledValue: '', + }); + + const disabledInput = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput + ); + await user.type(disabledInput, 't'); + + expect(onDisabledValueChange).toHaveBeenCalledTimes(1); + expect(onDisabledValueChange).toHaveBeenCalledWith('t'); + }); + + it('should handle all predefined value pair types correctly', () => { + const testCases = [ + { enabled: 'true', disabled: 'false', expected: 'True / False', hasCustomInputs: false }, + { enabled: '1', disabled: '0', expected: '1 / 0', hasCustomInputs: false }, + { enabled: 'yes', disabled: 'no', expected: 'Yes / No', hasCustomInputs: false }, + { enabled: 'custom', disabled: 'value', expected: 'Custom', hasCustomInputs: true }, + ]; + + testCases.forEach(({ enabled, disabled, expected, hasCustomInputs }) => { + const { unmount } = renderForm({ + enabledValue: enabled, + disabledValue: disabled, + }); + + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect) + ).toHaveValue(expected); + + if (hasCustomInputs) { + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput) + ).toBeInTheDocument(); + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput) + ).toBeInTheDocument(); + } else { + expect( + screen.queryByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput) + ).not.toBeInTheDocument(); + expect( + screen.queryByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput) + ).not.toBeInTheDocument(); + } + + unmount(); + }); + }); +}); diff --git a/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.tsx b/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.tsx new file mode 100644 index 00000000000..a14824ab84e --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/components/SwitchVariableForm.tsx @@ -0,0 +1,145 @@ +import { useState } from 'react'; + +import { selectors } from '@grafana/e2e-selectors'; +import { Trans, t } from '@grafana/i18n'; +import { Field, Combobox, Input, type ComboboxOption, Stack } from '@grafana/ui'; + +import { VariableLegend } from './VariableLegend'; + +interface SwitchVariableFormProps { + enabledValue: string; + disabledValue: string; + onEnabledValueChange: (value: string) => void; + onDisabledValueChange: (value: string) => void; +} + +const VALUE_PAIR_OPTIONS: Array> = [ + { label: 'True / False', value: 'boolean' }, + { label: '1 / 0', value: 'number' }, + { label: 'Yes / No', value: 'string' }, + { label: 'Custom', value: 'custom' }, +]; + +export function SwitchVariableForm({ + enabledValue, + disabledValue, + onEnabledValueChange, + onDisabledValueChange, +}: SwitchVariableFormProps) { + const currentValuePairType = getCurrentValuePairType(enabledValue, disabledValue); + const [isCustomValuePairType, setIsCustomValuePairType] = useState(currentValuePairType === 'custom'); + + const onValuePairTypeChange = (selection: ComboboxOption | null) => { + if (!selection?.value) { + return; + } + + switch (selection.value) { + case 'boolean': + onEnabledValueChange('true'); + onDisabledValueChange('false'); + setIsCustomValuePairType(false); + break; + case 'number': + onEnabledValueChange('1'); + onDisabledValueChange('0'); + setIsCustomValuePairType(false); + break; + case 'string': + onEnabledValueChange('yes'); + onDisabledValueChange('no'); + setIsCustomValuePairType(false); + break; + case 'custom': + setIsCustomValuePairType(true); + break; + } + }; + + return ( + <> + + Switch options + + + + + + + + {/* Custom value pair type */} + {isCustomValuePairType && ( + + + { + onEnabledValueChange(event.currentTarget.value); + }} + placeholder={t( + 'dashboard-scene.switch-variable-form.enabled-value-placeholder', + 'e.g. On, Enabled, Active' + )} + data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput} + /> + + + + onDisabledValueChange(event.currentTarget.value)} + placeholder={t( + 'dashboard-scene.switch-variable-form.disabled-value-placeholder', + 'e.g. Off, Disabled, Inactive' + )} + data-testid={selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput} + /> + + + )} + + + ); +} + +function getCurrentValuePairType(enabledValue: string, disabledValue: string) { + if (enabledValue === 'true' && disabledValue === 'false') { + return 'boolean'; + } + if (enabledValue === '1' && disabledValue === '0') { + return 'number'; + } + if (enabledValue === 'yes' && disabledValue === 'no') { + return 'string'; + } + return 'custom'; +} diff --git a/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.test.tsx b/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.test.tsx new file mode 100644 index 00000000000..055fdac1167 --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.test.tsx @@ -0,0 +1,155 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { selectors } from '@grafana/e2e-selectors'; +import { SwitchVariable } from '@grafana/scenes'; + +import { SwitchVariableEditor } from './SwitchVariableEditor'; + +describe('SwitchVariableEditor', () => { + it('should render the form with value pair type selector', () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'false', + enabledValue: 'true', + disabledValue: 'false', + }); + render(); + + expect(screen.getByText('Switch options')).toBeInTheDocument(); + expect(screen.getByText('Value pair type')).toBeInTheDocument(); + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect) + ).toBeInTheDocument(); + }); + + it('should show boolean value pair type for true/false values', () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'true', + enabledValue: 'true', + disabledValue: 'false', + }); + render(); + + const combobox = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect + ); + expect(combobox).toHaveDisplayValue('True / False'); + }); + + it('should show number value pair type for 1/0 values', () => { + const variable = new SwitchVariable({ + name: 'test', + value: '1', + enabledValue: '1', + disabledValue: '0', + }); + render(); + + const combobox = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect + ); + expect(combobox).toHaveDisplayValue('1 / 0'); + }); + + it('should show string value pair type for yes/no values', () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'yes', + enabledValue: 'yes', + disabledValue: 'no', + }); + render(); + + const combobox = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect + ); + expect(combobox).toHaveDisplayValue('Yes / No'); + }); + + it('should show custom value pair type and inputs for custom values', () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'on', + enabledValue: 'on', + disabledValue: 'off', + }); + render(); + + const combobox = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.valuePairTypeSelect + ); + expect(combobox).toHaveDisplayValue('Custom'); + + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput) + ).toBeInTheDocument(); + expect( + screen.getByTestId(selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput) + ).toBeInTheDocument(); + }); + + it('should update enabled value and current value when currently enabled', async () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'on', + enabledValue: 'on', + disabledValue: 'off', + }); + const user = userEvent.setup(); + + render(); + + const enabledInput = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.enabledValueInput + ); + await user.clear(enabledInput); + await user.type(enabledInput, 'active'); + + expect(variable.state.enabledValue).toBe('active'); + expect(variable.state.value).toBe('active'); + }); + + it('should update disabled value and current value when currently disabled', async () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'off', + enabledValue: 'on', + disabledValue: 'off', + }); + const user = userEvent.setup(); + + render(); + + const disabledInput = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput + ); + await user.clear(disabledInput); + await user.type(disabledInput, 'inactive'); + + expect(variable.state.disabledValue).toBe('inactive'); + expect(variable.state.value).toBe('inactive'); + }); + + it('should not update current value when changing non-current state value', async () => { + const variable = new SwitchVariable({ + name: 'test', + value: 'on', + enabledValue: 'on', + disabledValue: 'off', + }); + const user = userEvent.setup(); + + render(); + + const disabledInput = screen.getByTestId( + selectors.pages.Dashboard.Settings.Variables.Edit.SwitchVariable.disabledValueInput + ); + await user.clear(disabledInput); + await user.type(disabledInput, 'inactive'); + + expect(variable.state.disabledValue).toBe('inactive'); + expect(variable.state.value).toBe('on'); // Should remain unchanged + }); +}); diff --git a/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.tsx b/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.tsx new file mode 100644 index 00000000000..3656231c50e --- /dev/null +++ b/public/app/features/dashboard-scene/settings/variables/editors/SwitchVariableEditor.tsx @@ -0,0 +1,55 @@ +import { SceneVariable, SwitchVariable } from '@grafana/scenes'; +import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; + +import { SwitchVariableForm } from '../components/SwitchVariableForm'; + +interface SwitchVariableEditorProps { + variable: SwitchVariable; +} + +export function SwitchVariableEditor({ variable }: SwitchVariableEditorProps) { + const { value, enabledValue, disabledValue } = variable.useState(); + + const onEnabledValueChange = (newEnabledValue: string) => { + const isCurrentlyEnabled = value === enabledValue; + + if (isCurrentlyEnabled) { + variable.setState({ enabledValue: newEnabledValue, value: newEnabledValue }); + } else { + variable.setState({ enabledValue: newEnabledValue }); + } + }; + + const onDisabledValueChange = (newDisabledValue: string) => { + const isCurrentlyDisabled = value === disabledValue; + + if (isCurrentlyDisabled) { + variable.setState({ disabledValue: newDisabledValue, value: newDisabledValue }); + } else { + variable.setState({ disabledValue: newDisabledValue }); + } + }; + + return ( + + ); +} + +export function getSwitchVariableOptions(variable: SceneVariable): OptionsPaneItemDescriptor[] { + if (!(variable instanceof SwitchVariable)) { + console.warn('getSwitchVariableOptions: variable is not a SwitchVariable'); + return []; + } + + return [ + new OptionsPaneItemDescriptor({ + id: `variable-${variable.state.name}-value`, + render: () => , + }), + ]; +} diff --git a/public/app/features/dashboard-scene/settings/variables/utils.test.ts b/public/app/features/dashboard-scene/settings/variables/utils.test.ts index 642b6df7d92..2d9b07c1d38 100644 --- a/public/app/features/dashboard-scene/settings/variables/utils.test.ts +++ b/public/app/features/dashboard-scene/settings/variables/utils.test.ts @@ -147,7 +147,7 @@ describe('getVariableTypeSelectOptions', () => { it('should return an array of selectable values for editable variable types', () => { const editableVariables = getEditableVariables(); const options = getVariableTypeSelectOptions(); - expect(options).toHaveLength(8); + expect(options).toHaveLength(9); options.forEach((option, index) => { const editableType = EDITABLE_VARIABLES_SELECT_ORDER[index]; @@ -174,7 +174,7 @@ describe('getVariableTypeSelectOptions', () => { it('should return an array of selectable values for editable variable types', () => { const editableVariables = getEditableVariables(); const options = getVariableTypeSelectOptions(); - expect(options).toHaveLength(7); + expect(options).toHaveLength(8); options.forEach((option, index) => { const editableType = EDITABLE_VARIABLES_SELECT_ORDER[index]; diff --git a/public/app/features/dashboard-scene/settings/variables/utils.ts b/public/app/features/dashboard-scene/settings/variables/utils.ts index 684ba7b1ef0..adebfc52889 100644 --- a/public/app/features/dashboard-scene/settings/variables/utils.ts +++ b/public/app/features/dashboard-scene/settings/variables/utils.ts @@ -18,6 +18,7 @@ import { AdHocFiltersVariable, SceneVariableState, SceneVariableSet, + SwitchVariable, } from '@grafana/scenes'; import { VariableHide, VariableType } from '@grafana/schema'; import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; @@ -31,6 +32,7 @@ import { DataSourceVariableEditor, getDataSourceVariableOptions } from './editor import { getGroupByVariableOptions, GroupByVariableEditor } from './editors/GroupByVariableEditor'; import { getIntervalVariableOptions, IntervalVariableEditor } from './editors/IntervalVariableEditor'; import { getQueryVariableOptions, QueryVariableEditor } from './editors/QueryVariableEditor'; +import { getSwitchVariableOptions, SwitchVariableEditor } from './editors/SwitchVariableEditor'; import { TextBoxVariableEditor, getTextBoxVariableOptions } from './editors/TextBoxVariableEditor'; interface EditableVariableConfig { @@ -117,6 +119,15 @@ export const getEditableVariables: () => Record { }); }); + describe('when migrating a "switch" variable', () => { + const baseVariable: SwitchVariableModel = { + id: 'switch1', + global: false, + index: 0, + state: LoadingState.Done, + error: null, + name: 'switchVar', + label: 'Switch Label', + description: 'Switch Description', + type: 'switch', + rootStateKey: 'N4XLmH5Vz', + current: { + selected: true, + text: ['true'], + value: ['true'], + }, + hide: 0, + skipUrlSync: false, + options: [ + { + selected: false, + text: 'true', + value: 'true', + }, + { + selected: true, + text: 'false', + value: 'false', + }, + ], + query: '', + }; + const baseExpectedState = { + description: 'Switch Description', + enabledValue: 'true', + disabledValue: 'false', + hide: 0, + label: 'Switch Label', + name: 'switchVar', + skipUrlSync: false, + type: 'switch', + value: 'true', + }; + + it('should migrate a "switch" variable with "true" value', () => { + const variable: SwitchVariableModel = { + ...baseVariable, + current: { + selected: true, + text: 'true', + value: 'true', + }, + }; + + const migrated = createSceneVariableFromVariableModel(variable); + const { key, ...rest } = migrated.state; + + expect(migrated).toBeInstanceOf(SwitchVariable); + expect(rest).toEqual({ + ...baseExpectedState, + value: 'true', + }); + }); + + it('should migrate a "switch" variable with "false" value', () => { + const variable: SwitchVariableModel = { + ...baseVariable, + current: { + selected: true, + text: 'false', + value: 'false', + }, + }; + + const migrated = createSceneVariableFromVariableModel(variable); + const { key, ...rest } = migrated.state; + + expect(migrated).toBeInstanceOf(SwitchVariable); + expect(rest).toEqual({ + ...baseExpectedState, + value: 'false', + }); + }); + + it('should migrate a switch variable with array "true" value', () => { + const variable: SwitchVariableModel = { + ...baseVariable, + current: { + selected: true, + text: ['true'], + value: ['true'], + }, + }; + + const migrated = createSceneVariableFromVariableModel(variable); + const { key, ...rest } = migrated.state; + + expect(migrated).toBeInstanceOf(SwitchVariable); + expect(rest).toEqual({ + ...baseExpectedState, + value: 'true', + }); + }); + + it('should migrate a switch variable with array "false" value', () => { + const variable: SwitchVariableModel = { + ...baseVariable, + current: { + selected: true, + text: ['false'], + value: ['false'], + }, + }; + + const migrated = createSceneVariableFromVariableModel(variable); + const { key, ...rest } = migrated.state; + + expect(migrated).toBeInstanceOf(SwitchVariable); + expect(rest).toEqual({ + ...baseExpectedState, + value: 'false', + }); + }); + + it('should migrate a "switch" variable with a custom value', () => { + const variable: SwitchVariableModel = { + ...baseVariable, + current: { + selected: true, + text: 'on', + value: 'on', + }, + options: [ + { + selected: true, + text: 'on', + value: 'on', + }, + { + selected: false, + text: 'off', + value: 'off', + }, + ], + }; + + const migrated = createSceneVariableFromVariableModel(variable); + const { key, ...rest } = migrated.state; + + expect(migrated).toBeInstanceOf(SwitchVariable); + expect(rest).toEqual({ + ...baseExpectedState, + disabledValue: 'off', + enabledValue: 'on', + value: 'on', + }); + }); + }); + it.each(['system'])('should throw for unsupported (yet) variables', (type) => { const variable = { name: 'query0', diff --git a/public/app/features/dashboard-scene/utils/variables.ts b/public/app/features/dashboard-scene/utils/variables.ts index 43214dce91c..4f4ef802806 100644 --- a/public/app/features/dashboard-scene/utils/variables.ts +++ b/public/app/features/dashboard-scene/utils/variables.ts @@ -11,6 +11,7 @@ import { SceneVariable, SceneVariableSet, ScopesVariable, + SwitchVariable, TextBoxVariable, } from '@grafana/scenes'; import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; @@ -156,6 +157,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode ), }); } + // Custom variable if (variable.type === 'custom') { return new CustomVariable({ ...commonProperties, @@ -171,6 +173,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode hide: variable.hide, allowCustomValue: variable.allowCustomValue, }); + // Query variable } else if (variable.type === 'query') { return new QueryVariable({ ...commonProperties, @@ -196,6 +199,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode })), staticOptionsOrder: variable.staticOptionsOrder, }); + // Datasource variable } else if (variable.type === 'datasource') { return new DataSourceVariable({ ...commonProperties, @@ -212,6 +216,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode defaultOptionEnabled: variable.current?.value === DEFAULT_DATASOURCE && variable.current?.text === 'default', allowCustomValue: variable.allowCustomValue, }); + // Interval variable } else if (variable.type === 'interval') { const intervals = getIntervalsFromQueryString(variable.query); const currentInterval = getCurrentValueForOldIntervalModel(variable, intervals); @@ -226,6 +231,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); + // Constant variable } else if (variable.type === 'constant') { return new ConstantVariable({ ...commonProperties, @@ -233,6 +239,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); + // Textbox variable } else if (variable.type === 'textbox') { let val; if (!variable?.current?.value) { @@ -251,6 +258,7 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode skipUrlSync: variable.skipUrlSync, hide: variable.hide, }); + // Groupby variable } else if (config.featureToggles.groupByVariable && variable.type === 'groupby') { return new GroupByVariable({ ...commonProperties, @@ -264,6 +272,25 @@ export function createSceneVariableFromVariableModel(variable: TypedVariableMode defaultValue: variable.defaultValue, allowCustomValue: variable.allowCustomValue, }); + // Switch variable + // In the old variable model we are storing the enabled and disabled values in the options: + // the first option is the enabled value and the second is the disabled value + } else if (variable.type === 'switch') { + const pickFirstValue = (value: string | string[]) => { + if (Array.isArray(value)) { + return value[0]; + } + return value; + }; + + return new SwitchVariable({ + ...commonProperties, + value: pickFirstValue(variable.current?.value), + enabledValue: pickFirstValue(variable.options?.[0]?.value), + disabledValue: pickFirstValue(variable.options?.[1]?.value), + skipUrlSync: variable.skipUrlSync, + hide: variable.hide, + }); } else { throw new Error(`Scenes: Unsupported variable type ${variable.type}`); } diff --git a/public/app/features/dashboard-scene/v2schema/test-helpers.ts b/public/app/features/dashboard-scene/v2schema/test-helpers.ts index b26066d1ea3..a8f2c64e346 100644 --- a/public/app/features/dashboard-scene/v2schema/test-helpers.ts +++ b/public/app/features/dashboard-scene/v2schema/test-helpers.ts @@ -8,6 +8,7 @@ import { SceneQueryRunner, SceneVariable, SceneVariableState, + SwitchVariable, VizPanel, } from '@grafana/scenes'; import { Spec as DashboardV2Spec } from '@grafana/schema/dist/esm/schema/dashboard/v2'; @@ -43,7 +44,12 @@ export function validateVariable< ); expect(sceneVariable?.state.datasource?.type).toEqual(variableKind.group); expect(sceneVariable?.state.datasource?.uid).toEqual(variableKind.datasource?.name); - } else if (variableKind.kind !== 'AdhocVariable') { + } else if (variableKind.kind === 'SwitchVariable' && sceneVariable instanceof SwitchVariable) { + expect(sceneVariable).toBeInstanceOf(sceneVariableClass); + expect(scene.state?.$variables?.getByName(dashSpec.variables[index].spec.name)?.getValue()).toBe( + variableKind.spec.current + ); + } else if (variableKind.kind !== 'AdhocVariable' && variableKind.kind !== 'SwitchVariable') { expect(sceneVariable).toBeInstanceOf(sceneVariableClass); expect(scene.state?.$variables?.getByName(dashSpec.variables[index].spec.name)?.getValue()).toBe( variableKind.spec.current.value diff --git a/public/app/features/variables/guard.test.ts b/public/app/features/variables/guard.test.ts index 7e57f8422ad..d2094d74f4b 100644 --- a/public/app/features/variables/guard.test.ts +++ b/public/app/features/variables/guard.test.ts @@ -24,6 +24,7 @@ import { createOrgVariable, createQueryVariable, createSnapshotVariable, + createSwitchVariable, createTextBoxVariable, createUserVariable, } from './state/__tests__/fixtures'; @@ -177,6 +178,7 @@ describe('type guards', () => { dashboard: { variable: createDashboardVariable(), isMulti: false, hasOptions: false, hasCurrent: true }, custom: { variable: createCustomVariable(), isMulti: true, hasOptions: true, hasCurrent: true }, snapshot: { variable: createSnapshotVariable(), isMulti: false, hasOptions: true, hasCurrent: true }, + switch: { variable: createSwitchVariable(), isMulti: false, hasOptions: true, hasCurrent: true }, }; const variableFacts = Object.values(variableFactsObj); diff --git a/public/app/features/variables/state/__tests__/fixtures.ts b/public/app/features/variables/state/__tests__/fixtures.ts index f72326cd79b..ccd86d56ede 100644 --- a/public/app/features/variables/state/__tests__/fixtures.ts +++ b/public/app/features/variables/state/__tests__/fixtures.ts @@ -11,6 +11,7 @@ import { OrgVariableModel, QueryVariableModel, SnapshotVariableModel, + SwitchVariableModel, TextBoxVariableModel, UserVariableModel, VariableHide, @@ -209,3 +210,28 @@ export function createSnapshotVariable(input: Partial = { ...input, }; } + +export function createSwitchVariable(input: Partial = {}): SwitchVariableModel { + return { + ...createBaseVariableModel('switch'), + current: { + value: 'true', + text: 'true', + selected: true, + }, + options: [ + { + value: 'true', + text: 'true', + selected: true, + }, + { + value: 'false', + text: 'false', + selected: false, + }, + ], + query: '', + ...input, + }; +} diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json index 8ed054f3908..009c3daf324 100644 --- a/public/locales/en-US/grafana.json +++ b/public/locales/en-US/grafana.json @@ -5819,6 +5819,7 @@ "dynamically-switch-source-multiple-panels": "Dynamically switch the data source for multiple panels", "group": "Add keys to group by on the fly", "hidden-constant-variable": "A hidden constant variable, useful for metric prefixes in dashboards you want to share", + "users-enter-arbitrary-strings-switch": "A variable that can be toggled on and off", "users-enter-arbitrary-strings-textbox": "Users can enter any arbitrary strings in a textbox", "values-are-static-and-defined-manually": "Values are static and defined manually", "values-fetched-source-query": "Values are fetched from a data source query", @@ -5832,6 +5833,7 @@ "group-by": "Group by", "interval": "Interval", "query": "Query", + "switch": "Switch", "textbox": "Textbox" } }, @@ -6176,6 +6178,17 @@ "copy-to-clipboard-failed": "Copy to clipboard failed" } }, + "switch-variable-form": { + "disabled-value": "Disabled value", + "disabled-value-description": "Value when switch is disabled", + "disabled-value-placeholder": "e.g. Off, Disabled, Inactive", + "enabled-value": "Enabled value", + "enabled-value-description": "Value when switch is enabled", + "enabled-value-placeholder": "e.g. On, Enabled, Active", + "switch-options": "Switch options", + "value-pair-type": "Value pair type", + "value-pair-type-description": "Choose the type of values for the switch states" + }, "text-box-variable": { "name-default-value": "Default value" }, diff --git a/yarn.lock b/yarn.lock index af206586db1..4aad46d0157 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3524,11 +3524,11 @@ __metadata: languageName: unknown linkType: soft -"@grafana/scenes-react@npm:6.38.0": - version: 6.38.0 - resolution: "@grafana/scenes-react@npm:6.38.0" +"@grafana/scenes-react@npm:6.39.3": + version: 6.39.3 + resolution: "@grafana/scenes-react@npm:6.39.3" dependencies: - "@grafana/scenes": "npm:6.38.0" + "@grafana/scenes": "npm:6.39.3" lru-cache: "npm:^10.2.2" react-use: "npm:^17.4.0" peerDependencies: @@ -3540,13 +3540,13 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/7b38553f1950f6592eb24878061cc7c45fc2aa1776c4b1cd521c6995d11f8beb0b2b275afda0ebf0ec19b7f7c79b77126caad4843bc9a75bd09881645e882c91 + checksum: 10/7e989c0d34ab23add873fcdf8f2ebf2bb94c7cfd427631be13da4a08a0f78832c354868d97e584534a69a4bf4224fcb49a8d49fb16bf43cbed58203bd36c90d4 languageName: node linkType: hard -"@grafana/scenes@npm:6.38.0": - version: 6.38.0 - resolution: "@grafana/scenes@npm:6.38.0" +"@grafana/scenes@npm:6.39.3": + version: 6.39.3 + resolution: "@grafana/scenes@npm:6.39.3" dependencies: "@floating-ui/react": "npm:^0.26.16" "@leeoniya/ufuzzy": "npm:^1.0.16" @@ -3566,7 +3566,7 @@ __metadata: react: ^18.0.0 react-dom: ^18.0.0 react-router-dom: ^6.28.0 - checksum: 10/9372896e76271becb80e4a8691d8c51bc3b54b54d98c82f2953134f407a7370dc66a3e8afaa508003147e2f1b5b08d0ddbb6b1616a3a3ab3f7ad69fb941dd998 + checksum: 10/e5ddaf4f5e9afc7370eb4b6608d26056d1e4072465c2179e87415ac4ad01a4f8693bafaa372d7ed8ec6f295847561116ea85993cb5e5e6c4927fbb82b56f2e96 languageName: node linkType: hard @@ -18289,8 +18289,8 @@ __metadata: "@grafana/plugin-ui": "npm:^0.10.10" "@grafana/prometheus": "workspace:*" "@grafana/runtime": "workspace:*" - "@grafana/scenes": "npm:6.38.0" - "@grafana/scenes-react": "npm:6.38.0" + "@grafana/scenes": "npm:6.39.3" + "@grafana/scenes-react": "npm:6.39.3" "@grafana/schema": "workspace:*" "@grafana/sql": "workspace:*" "@grafana/test-utils": "workspace:*"