Dynamic dashboards: Persist conditional rendering (#102022)
* Dashboards: Add conditional rendering * Updates * Fixes * Code improvements * Code improvements * limit condition choices, add delete and clean up ui * add basic variable condition * add conditional rendering based on time range interval * adjust failing test * remove deprecated pseudo locale file * extract conditional rendering from behaviour to state property * clean up behaviour initialisation * clean up ts errors * adjust data condition to account for RowItem * persist-conditional-rendering * fix group value name and kind type * Fix types in base * minor style fix * Fix subscribes * notify change when deleting condition * fix hidden row item error * Remove option to have groups in groups * fix merge issue * address comments * subscribe to panel data change in data condition * Remove loop labels * only persist conditional rendering if root group has items * update backend types * Serialize variable conditional rendering operator as equals notEquals --------- Co-authored-by: Bogdan Matei <bogdan.matei@grafana.com> Co-authored-by: Sergej-Vlasov <sergej.s.vlasov@gmail.com>
This commit is contained in:
co-authored by
Bogdan Matei
Sergej-Vlasov
parent
8fd2a12670
commit
d07b1851c7
@@ -564,6 +564,7 @@ RowsLayoutRowKind: {
|
||||
RowsLayoutRowSpec: {
|
||||
title?: string
|
||||
collapsed: bool
|
||||
conditionalRendering?: ConditionalRenderingGroupKind
|
||||
repeat?: RowRepeatOptions
|
||||
layout: GridLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind
|
||||
}
|
||||
@@ -587,6 +588,7 @@ ResponsiveGridLayoutItemKind: {
|
||||
ResponsiveGridLayoutItemSpec: {
|
||||
element: ElementReference
|
||||
repeat?: ResponsiveGridRepeatOptions
|
||||
conditionalRendering?: ConditionalRenderingGroupKind
|
||||
}
|
||||
|
||||
TabsLayoutKind: {
|
||||
@@ -921,3 +923,42 @@ AdhocVariableKind: {
|
||||
kind: "AdhocVariable"
|
||||
spec: AdhocVariableSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingGroupKind: {
|
||||
kind: "ConditionalRenderingGroup"
|
||||
spec: ConditionalRenderingGroupSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingGroupSpec: {
|
||||
condition: "and" | "or"
|
||||
items: [...ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeIntervalKind]
|
||||
}
|
||||
|
||||
ConditionalRenderingVariableKind: {
|
||||
kind: "ConditionalRenderingVariable"
|
||||
spec: ConditionalRenderingVariableSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingVariableSpec: {
|
||||
variable: string
|
||||
operator: "equals" | "notEquals"
|
||||
value: string
|
||||
}
|
||||
|
||||
ConditionalRenderingDataKind: {
|
||||
kind: "ConditionalRenderingData"
|
||||
spec: ConditionalRenderingDataSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingDataSpec: {
|
||||
value: bool
|
||||
}
|
||||
|
||||
ConditionalRenderingTimeIntervalKind: {
|
||||
kind: "ConditionalRenderingTimeInterval"
|
||||
spec: ConditionalRenderingTimeIntervalSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingTimeIntervalSpec: {
|
||||
value: string
|
||||
}
|
||||
@@ -833,10 +833,11 @@ func NewDashboardRowsLayoutRowKind() *DashboardRowsLayoutRowKind {
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardRowsLayoutRowSpec struct {
|
||||
Title *string `json:"title,omitempty"`
|
||||
Collapsed bool `json:"collapsed"`
|
||||
Repeat *DashboardRowRepeatOptions `json:"repeat,omitempty"`
|
||||
Layout DashboardGridLayoutKindOrResponsiveGridLayoutKindOrTabsLayoutKind `json:"layout"`
|
||||
Title *string `json:"title,omitempty"`
|
||||
Collapsed bool `json:"collapsed"`
|
||||
ConditionalRendering *DashboardConditionalRenderingGroupKind `json:"conditionalRendering,omitempty"`
|
||||
Repeat *DashboardRowRepeatOptions `json:"repeat,omitempty"`
|
||||
Layout DashboardGridLayoutKindOrResponsiveGridLayoutKindOrTabsLayoutKind `json:"layout"`
|
||||
}
|
||||
|
||||
// NewDashboardRowsLayoutRowSpec creates a new DashboardRowsLayoutRowSpec object.
|
||||
@@ -846,6 +847,105 @@ func NewDashboardRowsLayoutRowSpec() *DashboardRowsLayoutRowSpec {
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingGroupKind struct {
|
||||
Kind string `json:"kind"`
|
||||
Spec DashboardConditionalRenderingGroupSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingGroupKind creates a new DashboardConditionalRenderingGroupKind object.
|
||||
func NewDashboardConditionalRenderingGroupKind() *DashboardConditionalRenderingGroupKind {
|
||||
return &DashboardConditionalRenderingGroupKind{
|
||||
Kind: "ConditionalRenderingGroup",
|
||||
Spec: *NewDashboardConditionalRenderingGroupSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingGroupSpec struct {
|
||||
Condition DashboardConditionalRenderingGroupSpecCondition `json:"condition"`
|
||||
Items []DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind `json:"items"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingGroupSpec creates a new DashboardConditionalRenderingGroupSpec object.
|
||||
func NewDashboardConditionalRenderingGroupSpec() *DashboardConditionalRenderingGroupSpec {
|
||||
return &DashboardConditionalRenderingGroupSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingVariableKind struct {
|
||||
Kind string `json:"kind"`
|
||||
Spec DashboardConditionalRenderingVariableSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingVariableKind creates a new DashboardConditionalRenderingVariableKind object.
|
||||
func NewDashboardConditionalRenderingVariableKind() *DashboardConditionalRenderingVariableKind {
|
||||
return &DashboardConditionalRenderingVariableKind{
|
||||
Kind: "ConditionalRenderingVariable",
|
||||
Spec: *NewDashboardConditionalRenderingVariableSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingVariableSpec struct {
|
||||
Variable string `json:"variable"`
|
||||
Operator DashboardConditionalRenderingVariableSpecOperator `json:"operator"`
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingVariableSpec creates a new DashboardConditionalRenderingVariableSpec object.
|
||||
func NewDashboardConditionalRenderingVariableSpec() *DashboardConditionalRenderingVariableSpec {
|
||||
return &DashboardConditionalRenderingVariableSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingDataKind struct {
|
||||
Kind string `json:"kind"`
|
||||
Spec DashboardConditionalRenderingDataSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingDataKind creates a new DashboardConditionalRenderingDataKind object.
|
||||
func NewDashboardConditionalRenderingDataKind() *DashboardConditionalRenderingDataKind {
|
||||
return &DashboardConditionalRenderingDataKind{
|
||||
Kind: "ConditionalRenderingData",
|
||||
Spec: *NewDashboardConditionalRenderingDataSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingDataSpec struct {
|
||||
Value bool `json:"value"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingDataSpec creates a new DashboardConditionalRenderingDataSpec object.
|
||||
func NewDashboardConditionalRenderingDataSpec() *DashboardConditionalRenderingDataSpec {
|
||||
return &DashboardConditionalRenderingDataSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingTimeIntervalKind struct {
|
||||
Kind string `json:"kind"`
|
||||
Spec DashboardConditionalRenderingTimeIntervalSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingTimeIntervalKind creates a new DashboardConditionalRenderingTimeIntervalKind object.
|
||||
func NewDashboardConditionalRenderingTimeIntervalKind() *DashboardConditionalRenderingTimeIntervalKind {
|
||||
return &DashboardConditionalRenderingTimeIntervalKind{
|
||||
Kind: "ConditionalRenderingTimeInterval",
|
||||
Spec: *NewDashboardConditionalRenderingTimeIntervalSpec(),
|
||||
}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingTimeIntervalSpec struct {
|
||||
Value string `json:"value"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingTimeIntervalSpec creates a new DashboardConditionalRenderingTimeIntervalSpec object.
|
||||
func NewDashboardConditionalRenderingTimeIntervalSpec() *DashboardConditionalRenderingTimeIntervalSpec {
|
||||
return &DashboardConditionalRenderingTimeIntervalSpec{}
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardResponsiveGridLayoutKind struct {
|
||||
Kind string `json:"kind"`
|
||||
@@ -888,8 +988,9 @@ func NewDashboardResponsiveGridLayoutItemKind() *DashboardResponsiveGridLayoutIt
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardResponsiveGridLayoutItemSpec struct {
|
||||
Element DashboardElementReference `json:"element"`
|
||||
Repeat *DashboardResponsiveGridRepeatOptions `json:"repeat,omitempty"`
|
||||
Element DashboardElementReference `json:"element"`
|
||||
Repeat *DashboardResponsiveGridRepeatOptions `json:"repeat,omitempty"`
|
||||
ConditionalRendering *DashboardConditionalRenderingGroupKind `json:"conditionalRendering,omitempty"`
|
||||
}
|
||||
|
||||
// NewDashboardResponsiveGridLayoutItemSpec creates a new DashboardResponsiveGridLayoutItemSpec object.
|
||||
@@ -1675,6 +1776,22 @@ const (
|
||||
DashboardRepeatOptionsDirectionV DashboardRepeatOptionsDirection = "v"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingGroupSpecCondition string
|
||||
|
||||
const (
|
||||
DashboardConditionalRenderingGroupSpecConditionAnd DashboardConditionalRenderingGroupSpecCondition = "and"
|
||||
DashboardConditionalRenderingGroupSpecConditionOr DashboardConditionalRenderingGroupSpecCondition = "or"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingVariableSpecOperator string
|
||||
|
||||
const (
|
||||
DashboardConditionalRenderingVariableSpecOperatorEquals DashboardConditionalRenderingVariableSpecOperator = "equals"
|
||||
DashboardConditionalRenderingVariableSpecOperatorNotEquals DashboardConditionalRenderingVariableSpecOperator = "notEquals"
|
||||
)
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardTimeSettingsSpecWeekStart string
|
||||
|
||||
@@ -1968,6 +2085,80 @@ func (resource *DashboardGridLayoutKindOrResponsiveGridLayoutKindOrTabsLayoutKin
|
||||
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator)
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind struct {
|
||||
ConditionalRenderingVariableKind *DashboardConditionalRenderingVariableKind `json:"ConditionalRenderingVariableKind,omitempty"`
|
||||
ConditionalRenderingDataKind *DashboardConditionalRenderingDataKind `json:"ConditionalRenderingDataKind,omitempty"`
|
||||
ConditionalRenderingTimeIntervalKind *DashboardConditionalRenderingTimeIntervalKind `json:"ConditionalRenderingTimeIntervalKind,omitempty"`
|
||||
}
|
||||
|
||||
// NewDashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind creates a new DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind object.
|
||||
func NewDashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind() *DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind {
|
||||
return &DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind{}
|
||||
}
|
||||
|
||||
// MarshalJSON implements a custom JSON marshalling logic to encode `DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind` as JSON.
|
||||
func (resource DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind) MarshalJSON() ([]byte, error) {
|
||||
if resource.ConditionalRenderingVariableKind != nil {
|
||||
return json.Marshal(resource.ConditionalRenderingVariableKind)
|
||||
}
|
||||
if resource.ConditionalRenderingDataKind != nil {
|
||||
return json.Marshal(resource.ConditionalRenderingDataKind)
|
||||
}
|
||||
if resource.ConditionalRenderingTimeIntervalKind != nil {
|
||||
return json.Marshal(resource.ConditionalRenderingTimeIntervalKind)
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no value for disjunction of refs")
|
||||
}
|
||||
|
||||
// UnmarshalJSON implements a custom JSON unmarshalling logic to decode `DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind` from JSON.
|
||||
func (resource *DashboardConditionalRenderingVariableKindOrConditionalRenderingDataKindOrConditionalRenderingTimeIntervalKind) UnmarshalJSON(raw []byte) error {
|
||||
if raw == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
// FIXME: this is wasteful, we need to find a more efficient way to unmarshal this.
|
||||
parsedAsMap := make(map[string]interface{})
|
||||
if err := json.Unmarshal(raw, &parsedAsMap); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
discriminator, found := parsedAsMap["kind"]
|
||||
if !found {
|
||||
return errors.New("discriminator field 'kind' not found in payload")
|
||||
}
|
||||
|
||||
switch discriminator {
|
||||
case "ConditionalRenderingData":
|
||||
var dashboardConditionalRenderingDataKind DashboardConditionalRenderingDataKind
|
||||
if err := json.Unmarshal(raw, &dashboardConditionalRenderingDataKind); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resource.ConditionalRenderingDataKind = &dashboardConditionalRenderingDataKind
|
||||
return nil
|
||||
case "ConditionalRenderingTimeInterval":
|
||||
var dashboardConditionalRenderingTimeIntervalKind DashboardConditionalRenderingTimeIntervalKind
|
||||
if err := json.Unmarshal(raw, &dashboardConditionalRenderingTimeIntervalKind); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resource.ConditionalRenderingTimeIntervalKind = &dashboardConditionalRenderingTimeIntervalKind
|
||||
return nil
|
||||
case "ConditionalRenderingVariable":
|
||||
var dashboardConditionalRenderingVariableKind DashboardConditionalRenderingVariableKind
|
||||
if err := json.Unmarshal(raw, &dashboardConditionalRenderingVariableKind); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
resource.ConditionalRenderingVariableKind = &dashboardConditionalRenderingVariableKind
|
||||
return nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("could not unmarshal resource with `kind = %v`", discriminator)
|
||||
}
|
||||
|
||||
// +k8s:openapi-gen=true
|
||||
type DashboardGridLayoutKindOrRowsLayoutKindOrResponsiveGridLayoutKind struct {
|
||||
GridLayoutKind *DashboardGridLayoutKind `json:"GridLayoutKind,omitempty"`
|
||||
|
||||
@@ -553,6 +553,7 @@ RowsLayoutRowSpec: {
|
||||
title?: string
|
||||
collapsed: bool
|
||||
repeat?: RowRepeatOptions
|
||||
conditionalRendering?: ConditionalRenderingGroupKind
|
||||
layout: GridLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind
|
||||
}
|
||||
|
||||
@@ -575,6 +576,7 @@ ResponsiveGridLayoutItemKind: {
|
||||
ResponsiveGridLayoutItemSpec: {
|
||||
element: ElementReference
|
||||
repeat?: ResponsiveGridRepeatOptions
|
||||
conditionalRendering?: ConditionalRenderingGroupKind
|
||||
}
|
||||
|
||||
TabsLayoutKind: {
|
||||
@@ -913,3 +915,42 @@ AdhocVariableKind: {
|
||||
kind: "AdhocVariable"
|
||||
spec: AdhocVariableSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingGroupKind: {
|
||||
kind: "ConditionalRenderingGroup"
|
||||
spec: ConditionalRenderingGroupSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingGroupSpec: {
|
||||
condition: "and" | "or"
|
||||
items: [...ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeIntervalKind]
|
||||
}
|
||||
|
||||
ConditionalRenderingVariableKind: {
|
||||
kind: "ConditionalRenderingVariable"
|
||||
spec: ConditionalRenderingVariableSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingVariableSpec: {
|
||||
variable: string
|
||||
operator: "equals" | "notEquals"
|
||||
value: string
|
||||
}
|
||||
|
||||
ConditionalRenderingDataKind: {
|
||||
kind: "ConditionalRenderingData"
|
||||
spec: ConditionalRenderingDataSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingDataSpec: {
|
||||
value: bool
|
||||
}
|
||||
|
||||
ConditionalRenderingTimeIntervalKind: {
|
||||
kind: "ConditionalRenderingTimeInterval"
|
||||
spec: ConditionalRenderingTimeIntervalSpec
|
||||
}
|
||||
|
||||
ConditionalRenderingTimeIntervalSpec: {
|
||||
value: string
|
||||
}
|
||||
@@ -825,6 +825,7 @@ export interface RowsLayoutRowSpec {
|
||||
title?: string;
|
||||
collapsed: boolean;
|
||||
repeat?: RowRepeatOptions;
|
||||
conditionalRendering?: ConditionalRenderingGroupKind;
|
||||
layout: GridLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind;
|
||||
}
|
||||
|
||||
@@ -868,6 +869,7 @@ export const defaultResponsiveGridLayoutItemKind = (): ResponsiveGridLayoutItemK
|
||||
export interface ResponsiveGridLayoutItemSpec {
|
||||
element: ElementReference;
|
||||
repeat?: ResponsiveGridRepeatOptions;
|
||||
conditionalRendering?: ConditionalRenderingGroupKind;
|
||||
}
|
||||
|
||||
export const defaultResponsiveGridLayoutItemSpec = (): ResponsiveGridLayoutItemSpec => ({
|
||||
@@ -1401,3 +1403,81 @@ export const defaultAdhocVariableKind = (): AdhocVariableKind => ({
|
||||
spec: defaultAdhocVariableSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingGroupKind {
|
||||
kind: "ConditionalRenderingGroup";
|
||||
spec: ConditionalRenderingGroupSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingGroupKind = (): ConditionalRenderingGroupKind => ({
|
||||
kind: "ConditionalRenderingGroup",
|
||||
spec: defaultConditionalRenderingGroupSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingGroupSpec {
|
||||
condition: "and" | "or";
|
||||
items: (ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeIntervalKind)[];
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingGroupSpec = (): ConditionalRenderingGroupSpec => ({
|
||||
condition: "and",
|
||||
items: [],
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingVariableKind {
|
||||
kind: "ConditionalRenderingVariable";
|
||||
spec: ConditionalRenderingVariableSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingVariableKind = (): ConditionalRenderingVariableKind => ({
|
||||
kind: "ConditionalRenderingVariable",
|
||||
spec: defaultConditionalRenderingVariableSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingVariableSpec {
|
||||
variable: string;
|
||||
operator: "equals" | "notEquals";
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingVariableSpec = (): ConditionalRenderingVariableSpec => ({
|
||||
variable: "",
|
||||
operator: "equals",
|
||||
value: "",
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingDataKind {
|
||||
kind: "ConditionalRenderingData";
|
||||
spec: ConditionalRenderingDataSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingDataKind = (): ConditionalRenderingDataKind => ({
|
||||
kind: "ConditionalRenderingData",
|
||||
spec: defaultConditionalRenderingDataSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingDataSpec {
|
||||
value: boolean;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingDataSpec = (): ConditionalRenderingDataSpec => ({
|
||||
value: false,
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingTimeIntervalKind {
|
||||
kind: "ConditionalRenderingTimeInterval";
|
||||
spec: ConditionalRenderingTimeIntervalSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingTimeIntervalKind = (): ConditionalRenderingTimeIntervalKind => ({
|
||||
kind: "ConditionalRenderingTimeInterval",
|
||||
spec: defaultConditionalRenderingTimeIntervalSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingTimeIntervalSpec {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingTimeIntervalSpec = (): ConditionalRenderingTimeIntervalSpec => ({
|
||||
value: "",
|
||||
});
|
||||
|
||||
|
||||
@@ -692,6 +692,7 @@ export const defaultRowsLayoutRowKind = (): RowsLayoutRowKind => ({
|
||||
export interface RowsLayoutRowSpec {
|
||||
title?: string;
|
||||
collapsed: boolean;
|
||||
conditionalRendering?: ConditionalRenderingGroupKind;
|
||||
repeat?: RowRepeatOptions;
|
||||
layout: GridLayoutKind | ResponsiveGridLayoutKind | TabsLayoutKind;
|
||||
}
|
||||
@@ -701,6 +702,84 @@ export const defaultRowsLayoutRowSpec = (): RowsLayoutRowSpec => ({
|
||||
layout: defaultGridLayoutKind(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingGroupKind {
|
||||
kind: "ConditionalRenderingGroup";
|
||||
spec: ConditionalRenderingGroupSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingGroupKind = (): ConditionalRenderingGroupKind => ({
|
||||
kind: "ConditionalRenderingGroup",
|
||||
spec: defaultConditionalRenderingGroupSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingGroupSpec {
|
||||
condition: "and" | "or";
|
||||
items: (ConditionalRenderingVariableKind | ConditionalRenderingDataKind | ConditionalRenderingTimeIntervalKind)[];
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingGroupSpec = (): ConditionalRenderingGroupSpec => ({
|
||||
condition: "and",
|
||||
items: [],
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingVariableKind {
|
||||
kind: "ConditionalRenderingVariable";
|
||||
spec: ConditionalRenderingVariableSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingVariableKind = (): ConditionalRenderingVariableKind => ({
|
||||
kind: "ConditionalRenderingVariable",
|
||||
spec: defaultConditionalRenderingVariableSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingVariableSpec {
|
||||
variable: string;
|
||||
operator: "equals" | "notEquals";
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingVariableSpec = (): ConditionalRenderingVariableSpec => ({
|
||||
variable: "",
|
||||
operator: "equals",
|
||||
value: "",
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingDataKind {
|
||||
kind: "ConditionalRenderingData";
|
||||
spec: ConditionalRenderingDataSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingDataKind = (): ConditionalRenderingDataKind => ({
|
||||
kind: "ConditionalRenderingData",
|
||||
spec: defaultConditionalRenderingDataSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingDataSpec {
|
||||
value: boolean;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingDataSpec = (): ConditionalRenderingDataSpec => ({
|
||||
value: false,
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingTimeIntervalKind {
|
||||
kind: "ConditionalRenderingTimeInterval";
|
||||
spec: ConditionalRenderingTimeIntervalSpec;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingTimeIntervalKind = (): ConditionalRenderingTimeIntervalKind => ({
|
||||
kind: "ConditionalRenderingTimeInterval",
|
||||
spec: defaultConditionalRenderingTimeIntervalSpec(),
|
||||
});
|
||||
|
||||
export interface ConditionalRenderingTimeIntervalSpec {
|
||||
value: string;
|
||||
}
|
||||
|
||||
export const defaultConditionalRenderingTimeIntervalSpec = (): ConditionalRenderingTimeIntervalSpec => ({
|
||||
value: "",
|
||||
});
|
||||
|
||||
export interface ResponsiveGridLayoutKind {
|
||||
kind: "ResponsiveGridLayout";
|
||||
spec: ResponsiveGridLayoutSpec;
|
||||
@@ -736,6 +815,7 @@ export const defaultResponsiveGridLayoutItemKind = (): ResponsiveGridLayoutItemK
|
||||
export interface ResponsiveGridLayoutItemSpec {
|
||||
element: ElementReference;
|
||||
repeat?: ResponsiveGridRepeatOptions;
|
||||
conditionalRendering?: ConditionalRenderingGroupKind;
|
||||
}
|
||||
|
||||
export const defaultResponsiveGridLayoutItemSpec = (): ResponsiveGridLayoutItemSpec => ({
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { SceneComponentProps, SceneObjectBase, SceneObjectState } from '@grafana/scenes';
|
||||
import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
|
||||
import { ConditionalRenderingGroup } from './ConditionalRenderingGroup';
|
||||
|
||||
@@ -36,6 +37,10 @@ export class ConditionalRendering extends SceneObjectBase<ConditionalRenderingSt
|
||||
public static createEmpty(): ConditionalRendering {
|
||||
return new ConditionalRendering({ rootGroup: ConditionalRenderingGroup.createEmpty() });
|
||||
}
|
||||
|
||||
public serialize(): ConditionalRenderingGroupKind {
|
||||
return this.state.rootGroup.serialize();
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionalRenderingRenderer({ model }: SceneComponentProps<ConditionalRendering>) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { SceneComponentProps, sceneGraph, SceneObjectBase, SceneObjectState } fr
|
||||
|
||||
import { ConditionalRendering } from './ConditionalRendering';
|
||||
import { ConditionalRenderingGroup } from './ConditionalRenderingGroup';
|
||||
import { ConditionalRenderingKindTypes } from './serializers';
|
||||
import { ConditionValues } from './shared';
|
||||
|
||||
export interface ConditionalRenderingBaseState<V = ConditionValues> extends SceneObjectState {
|
||||
@@ -34,6 +35,8 @@ export abstract class ConditionalRenderingBase<
|
||||
|
||||
public abstract readonly title: string;
|
||||
|
||||
public abstract serialize(): ConditionalRenderingKindTypes;
|
||||
|
||||
public abstract evaluate(): boolean;
|
||||
|
||||
public abstract render(): ReactNode;
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { ReactNode, useMemo } from 'react';
|
||||
|
||||
import { PanelData, SelectableValue } from '@grafana/data';
|
||||
import { SceneComponentProps, SceneDataProvider, sceneGraph } from '@grafana/scenes';
|
||||
import { ConditionalRenderingDataKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { RadioButtonGroup, Stack } from '@grafana/ui';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
@@ -112,6 +113,15 @@ export class ConditionalRenderingData extends ConditionalRenderingBase<Condition
|
||||
public onDelete() {
|
||||
handleDeleteNonGroupCondition(this);
|
||||
}
|
||||
|
||||
public serialize(): ConditionalRenderingDataKind {
|
||||
return {
|
||||
kind: 'ConditionalRenderingData',
|
||||
spec: {
|
||||
value: this.state.value,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionalRenderingDataRenderer({ model }: SceneComponentProps<ConditionalRenderingData>) {
|
||||
|
||||
+16
@@ -3,6 +3,7 @@ import { Fragment, ReactNode, useMemo } from 'react';
|
||||
|
||||
import { GrafanaTheme2, SelectableValue } from '@grafana/data';
|
||||
import { SceneComponentProps } from '@grafana/scenes';
|
||||
import { ConditionalRenderingGroupKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { Divider, Dropdown, Field, Menu, RadioButtonGroup, Stack, ToolbarButton, useStyles2 } from '@grafana/ui';
|
||||
import { t, Trans } from 'app/core/internationalization';
|
||||
|
||||
@@ -68,6 +69,21 @@ export class ConditionalRenderingGroup extends ConditionalRenderingBase<Conditio
|
||||
}
|
||||
this.getConditionalLogicRoot().notifyChange();
|
||||
}
|
||||
|
||||
public serialize(): ConditionalRenderingGroupKind {
|
||||
if (this.state.value.some((item) => item instanceof ConditionalRenderingGroup)) {
|
||||
throw new Error('ConditionalRenderingGroup cannot contain nested ConditionalRenderingGroups');
|
||||
}
|
||||
return {
|
||||
kind: 'ConditionalRenderingGroup',
|
||||
spec: {
|
||||
condition: this.state.condition,
|
||||
items: this.state.value
|
||||
.map((condition) => condition.serialize())
|
||||
.filter((item) => item.kind !== 'ConditionalRenderingGroup'),
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionalRenderingGroupRenderer({ model }: SceneComponentProps<ConditionalRenderingGroup>) {
|
||||
|
||||
+10
@@ -2,6 +2,7 @@ import { ReactNode, useState } from 'react';
|
||||
|
||||
import { rangeUtil } from '@grafana/data';
|
||||
import { SceneComponentProps, sceneGraph } from '@grafana/scenes';
|
||||
import { ConditionalRenderingTimeIntervalKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { Field, Input, Stack } from '@grafana/ui';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
@@ -54,6 +55,15 @@ export class ConditionalRenderingInterval extends ConditionalRenderingBase<Condi
|
||||
public onDelete() {
|
||||
handleDeleteNonGroupCondition(this);
|
||||
}
|
||||
|
||||
public serialize(): ConditionalRenderingTimeIntervalKind {
|
||||
return {
|
||||
kind: 'ConditionalRenderingTimeInterval',
|
||||
spec: {
|
||||
value: this.state.value,
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionalRenderingIntervalRenderer({ model }: SceneComponentProps<ConditionalRenderingInterval>) {
|
||||
|
||||
+30
-20
@@ -1,8 +1,8 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { ReactNode, useMemo } from 'react';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { SceneComponentProps, sceneGraph, VariableDependencyConfig } from '@grafana/scenes';
|
||||
import { SceneComponentProps, sceneGraph } from '@grafana/scenes';
|
||||
import { ConditionalRenderingVariableKind } from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { Combobox, ComboboxOption, Field, Input, Stack, useStyles2 } from '@grafana/ui';
|
||||
import { t } from 'app/core/internationalization';
|
||||
|
||||
@@ -16,21 +16,13 @@ export type VariableConditionValue = {
|
||||
value: string;
|
||||
};
|
||||
|
||||
type ConditionalRenderingVariableState = ConditionalRenderingBaseState<VariableConditionValue>;
|
||||
interface ConditionalRenderingVariableState extends ConditionalRenderingBaseState<VariableConditionValue> {}
|
||||
|
||||
export class ConditionalRenderingVariable extends ConditionalRenderingBase<ConditionalRenderingVariableState> {
|
||||
public get title(): string {
|
||||
return t('dashboard.conditional-rendering.variable.label', 'Variable');
|
||||
}
|
||||
|
||||
protected _variableDependency = new VariableDependencyConfig(this, {
|
||||
onAnyVariableChanged: (v) => {
|
||||
if (v.state.name === this.state.value.name) {
|
||||
this.getConditionalLogicRoot().notifyChange();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
public evaluate(): boolean {
|
||||
if (!this.state.value.name) {
|
||||
return true;
|
||||
@@ -41,10 +33,15 @@ export class ConditionalRenderingVariable extends ConditionalRenderingBase<Condi
|
||||
if (!variable) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const value = variable.getValue();
|
||||
|
||||
let hit = Array.isArray(value) ? value.includes(this.state.value.value) : value === this.state.value.value;
|
||||
let hit: boolean;
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
hit = value.includes(this.state.value.value);
|
||||
} else {
|
||||
hit = value === this.state.value.value;
|
||||
}
|
||||
|
||||
if (this.state.value.operator === '!=') {
|
||||
hit = !hit;
|
||||
@@ -57,17 +54,30 @@ export class ConditionalRenderingVariable extends ConditionalRenderingBase<Condi
|
||||
return <ConditionalRenderingVariableRenderer model={this} />;
|
||||
}
|
||||
|
||||
public serialize(): ConditionalRenderingVariableKind {
|
||||
return {
|
||||
kind: 'ConditionalRenderingVariable',
|
||||
spec: {
|
||||
variable: this.state.value.name,
|
||||
operator: this.state.value.operator === '=' ? 'equals' : 'notEquals',
|
||||
value: this.state.value.value,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
public getVariableOptions(): Array<ComboboxOption<string>> {
|
||||
return sceneGraph
|
||||
.getVariables(this)
|
||||
.state.variables.map((v) => ({ value: v.state.name, label: v.state.label ?? v.state.name }));
|
||||
}
|
||||
|
||||
public onDelete() {
|
||||
handleDeleteNonGroupCondition(this);
|
||||
}
|
||||
}
|
||||
|
||||
function ConditionalRenderingVariableRenderer({ model }: SceneComponentProps<ConditionalRenderingVariable>) {
|
||||
const variables = useMemo(() => sceneGraph.getVariables(model), [model]);
|
||||
const variableNames = useMemo(
|
||||
() => variables.state.variables.map((v) => ({ value: v.state.name, label: v.state.label ?? v.state.name })),
|
||||
[variables.state.variables]
|
||||
);
|
||||
const variableNames = useMemo(() => model.getVariableOptions(), [model]);
|
||||
const operatorOptions: Array<ComboboxOption<'=' | '!='>> = useMemo(
|
||||
() => [
|
||||
{ value: '=', description: t('dashboard.conditional-rendering.variable.operator.equals', 'Equals') },
|
||||
@@ -116,11 +126,11 @@ function ConditionalRenderingVariableRenderer({ model }: SceneComponentProps<Con
|
||||
);
|
||||
}
|
||||
|
||||
const getStyles = (theme: GrafanaTheme2) => ({
|
||||
const getStyles = () => ({
|
||||
variableNameSelect: css({
|
||||
flexGrow: 1,
|
||||
}),
|
||||
operatorSelect: css({
|
||||
width: theme.spacing(12),
|
||||
width: '6rem',
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
import { Registry, RegistryItem } from '@grafana/data';
|
||||
import {
|
||||
ConditionalRenderingGroupKind,
|
||||
ConditionalRenderingVariableKind,
|
||||
ConditionalRenderingDataKind,
|
||||
ConditionalRenderingTimeIntervalKind,
|
||||
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
|
||||
import { ConditionalRenderingData } from './ConditionalRenderingData';
|
||||
import { ConditionalRenderingGroup } from './ConditionalRenderingGroup';
|
||||
import { ConditionalRenderingInterval } from './ConditionalRenderingInterval';
|
||||
import { ConditionalRenderingVariable } from './ConditionalRenderingVariable';
|
||||
|
||||
export type ConditionalRenderingKindTypes =
|
||||
| ConditionalRenderingGroupKind
|
||||
| ConditionalRenderingVariableKind
|
||||
| ConditionalRenderingDataKind
|
||||
| ConditionalRenderingTimeIntervalKind;
|
||||
|
||||
export interface ConditionalRenderingSerializer {
|
||||
deserialize(
|
||||
model: ConditionalRenderingKindTypes
|
||||
): ConditionalRenderingGroup | ConditionalRenderingVariable | ConditionalRenderingData | ConditionalRenderingInterval;
|
||||
}
|
||||
|
||||
interface ConditionalRenderingSerializerRegistryItem extends RegistryItem {
|
||||
serializer: ConditionalRenderingSerializer;
|
||||
}
|
||||
|
||||
export class ConditionalRenderingGroupSerializer implements ConditionalRenderingSerializer {
|
||||
deserialize(model: ConditionalRenderingGroupKind): ConditionalRenderingGroup {
|
||||
return new ConditionalRenderingGroup({
|
||||
condition: model.spec.condition,
|
||||
value: model.spec.items.map((item: ConditionalRenderingKindTypes) => {
|
||||
const serializerRegistryItem = conditionalRenderingSerializerRegistry.getIfExists(item.kind);
|
||||
if (!serializerRegistryItem) {
|
||||
throw new Error(`No serializer found for conditional rendering kind: ${item.kind}`);
|
||||
}
|
||||
return serializerRegistryItem.serializer.deserialize(item);
|
||||
}),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ConditionalRenderingVariableSerializer implements ConditionalRenderingSerializer {
|
||||
deserialize(model: ConditionalRenderingVariableKind): ConditionalRenderingVariable {
|
||||
return new ConditionalRenderingVariable({
|
||||
value: {
|
||||
name: model.spec.variable,
|
||||
operator: model.spec.operator === 'equals' ? '=' : '!=',
|
||||
value: model.spec.value,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ConditionalRenderingDataSerializer implements ConditionalRenderingSerializer {
|
||||
deserialize(model: ConditionalRenderingDataKind): ConditionalRenderingData {
|
||||
return new ConditionalRenderingData({
|
||||
value: model.spec.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export class ConditionalRenderingIntervalSerializer implements ConditionalRenderingSerializer {
|
||||
deserialize(model: ConditionalRenderingTimeIntervalKind): ConditionalRenderingInterval {
|
||||
return new ConditionalRenderingInterval({
|
||||
value: model.spec.value,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export const conditionalRenderingSerializerRegistry = new Registry<ConditionalRenderingSerializerRegistryItem>(() => {
|
||||
return [
|
||||
{
|
||||
id: 'ConditionalRenderingGroup',
|
||||
name: 'Group',
|
||||
serializer: new ConditionalRenderingGroupSerializer(),
|
||||
},
|
||||
{
|
||||
id: 'ConditionalRenderingVariable',
|
||||
name: 'Variable',
|
||||
serializer: new ConditionalRenderingVariableSerializer(),
|
||||
},
|
||||
{
|
||||
id: 'ConditionalRenderingData',
|
||||
name: 'Data',
|
||||
serializer: new ConditionalRenderingDataSerializer(),
|
||||
},
|
||||
{
|
||||
id: 'ConditionalRenderingTimeInterval',
|
||||
name: 'Time Interval',
|
||||
serializer: new ConditionalRenderingIntervalSerializer(),
|
||||
},
|
||||
];
|
||||
});
|
||||
+8
-1
@@ -7,7 +7,7 @@ import { DashboardLayoutManager, LayoutManagerSerializer } from '../../scene/typ
|
||||
import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph';
|
||||
import { getGridItemKeyForPanelId } from '../../utils/utils';
|
||||
|
||||
import { buildLibraryPanel, buildVizPanel } from './utils';
|
||||
import { buildLibraryPanel, buildVizPanel, getConditionalRendering } from './utils';
|
||||
|
||||
export class ResponsiveGridLayoutSerializer implements LayoutManagerSerializer {
|
||||
serialize(layoutManager: ResponsiveGridLayoutManager): DashboardV2Spec['layout'] {
|
||||
@@ -35,6 +35,12 @@ export class ResponsiveGridLayoutSerializer implements LayoutManagerSerializer {
|
||||
},
|
||||
};
|
||||
|
||||
const conditionalRenderingRootGroup = child.state.conditionalRendering?.serialize();
|
||||
// Only serialize the conditional rendering if it has items
|
||||
if (conditionalRenderingRootGroup?.spec.items.length) {
|
||||
layoutItem.spec.conditionalRendering = conditionalRenderingRootGroup;
|
||||
}
|
||||
|
||||
if (child.state.variableName) {
|
||||
layoutItem.spec.repeat = {
|
||||
mode: 'variable',
|
||||
@@ -62,6 +68,7 @@ export class ResponsiveGridLayoutSerializer implements LayoutManagerSerializer {
|
||||
key: getGridItemKeyForPanelId(panel.spec.id),
|
||||
body: panel.kind === 'LibraryPanel' ? buildLibraryPanel(panel) : buildVizPanel(panel),
|
||||
variableName: item.spec.repeat?.value,
|
||||
conditionalRendering: getConditionalRendering(item),
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
+9
-1
@@ -7,7 +7,7 @@ import { RowsLayoutManager } from '../../scene/layout-rows/RowsLayoutManager';
|
||||
import { LayoutManagerSerializer } from '../../scene/types/DashboardLayoutManager';
|
||||
|
||||
import { layoutSerializerRegistry } from './layoutSerializerRegistry';
|
||||
import { getLayout } from './utils';
|
||||
import { getConditionalRendering, getLayout } from './utils';
|
||||
|
||||
export class RowsLayoutSerializer implements LayoutManagerSerializer {
|
||||
serialize(layoutManager: RowsLayoutManager): DashboardV2Spec['layout'] {
|
||||
@@ -28,6 +28,12 @@ export class RowsLayoutSerializer implements LayoutManagerSerializer {
|
||||
},
|
||||
};
|
||||
|
||||
const conditionalRenderingRootGroup = row.state.conditionalRendering?.serialize();
|
||||
// Only serialize the conditional rendering if it has items
|
||||
if (conditionalRenderingRootGroup?.spec.items.length) {
|
||||
rowKind.spec.conditionalRendering = conditionalRenderingRootGroup;
|
||||
}
|
||||
|
||||
if (row.state.$behaviors) {
|
||||
for (const behavior of row.state.$behaviors) {
|
||||
if (behavior instanceof RowItemRepeaterBehavior) {
|
||||
@@ -58,11 +64,13 @@ export class RowsLayoutSerializer implements LayoutManagerSerializer {
|
||||
if (row.spec.repeat) {
|
||||
behaviors.push(new RowItemRepeaterBehavior({ variableName: row.spec.repeat.value }));
|
||||
}
|
||||
|
||||
return new RowItem({
|
||||
title: row.spec.title,
|
||||
isCollapsed: row.spec.collapsed,
|
||||
$behaviors: behaviors,
|
||||
layout: layoutSerializerRegistry.get(layout.kind).serializer.deserialize(layout, elements, preload),
|
||||
conditionalRendering: getConditionalRendering(row),
|
||||
});
|
||||
});
|
||||
return new RowsLayoutManager({ rows });
|
||||
|
||||
@@ -12,12 +12,17 @@ import {
|
||||
import { DataSourceRef } from '@grafana/schema/dist/esm/index.gen';
|
||||
import {
|
||||
DashboardV2Spec,
|
||||
ResponsiveGridLayoutItemKind,
|
||||
RowsLayoutRowKind,
|
||||
LibraryPanelKind,
|
||||
PanelKind,
|
||||
PanelQueryKind,
|
||||
} from '@grafana/schema/dist/esm/schema/dashboard/v2alpha0';
|
||||
import { MIXED_DATASOURCE_NAME } from 'app/plugins/datasource/mixed/MixedDataSource';
|
||||
|
||||
import { ConditionalRendering } from '../../conditional-rendering/ConditionalRendering';
|
||||
import { ConditionalRenderingGroup } from '../../conditional-rendering/ConditionalRenderingGroup';
|
||||
import { conditionalRenderingSerializerRegistry } from '../../conditional-rendering/serializers';
|
||||
import { DashboardDatasourceBehaviour } from '../../scene/DashboardDatasourceBehaviour';
|
||||
import { LibraryPanelBehavior } from '../../scene/LibraryPanelBehavior';
|
||||
import { VizPanelLinks, VizPanelLinksMenu } from '../../scene/PanelLinks';
|
||||
@@ -202,3 +207,18 @@ export function getLayout(sceneState: DashboardLayoutManager): DashboardV2Spec['
|
||||
}
|
||||
return registryItem.serializer.serialize(sceneState);
|
||||
}
|
||||
|
||||
export function getConditionalRendering(item: RowsLayoutRowKind | ResponsiveGridLayoutItemKind): ConditionalRendering {
|
||||
if (!item.spec.conditionalRendering) {
|
||||
return ConditionalRendering.createEmpty();
|
||||
}
|
||||
const rootGroup = conditionalRenderingSerializerRegistry
|
||||
.get(item.spec.conditionalRendering.kind)
|
||||
.serializer.deserialize(item.spec.conditionalRendering);
|
||||
|
||||
if (rootGroup && !(rootGroup instanceof ConditionalRenderingGroup)) {
|
||||
throw new Error(`Conditional rendering must always start with a root group`);
|
||||
}
|
||||
|
||||
return new ConditionalRendering({ rootGroup: rootGroup });
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user