) {
isEditing && isCollapsed && styles.wrapperEditingCollapsed,
isCollapsed && styles.wrapperCollapsed,
shouldGrow && styles.wrapperGrow,
+ isHiddenButVisibleElement && 'dashboard-visible-hidden-element',
!isClone && isSelected && 'dashboard-selected-element',
!isClone && !isSelected && selectableHighlight && 'dashboard-selectable-element'
)}
- ref={ref}
onPointerDown={onSelect}
>
{(!isHeaderHidden || (isEditing && showHiddenElements)) && (
@@ -58,11 +73,11 @@ export function RowItemRenderer({ model }: SceneComponentProps) {
? t('dashboard.rows-layout.row.expand', 'Expand row')
: t('dashboard.rows-layout.row.collapse', 'Collapse row')
}
- data-testid={selectors.components.DashboardRow.title(titleInterpolated!)}
+ data-testid={selectors.components.DashboardRow.title(title!)}
>
- {titleInterpolated}
+ {title}
{!isClone && isEditing && }
diff --git a/public/app/features/dashboard-scene/utils/clone.ts b/public/app/features/dashboard-scene/utils/clone.ts
index 05d9459e0e2..f084b2e0182 100644
--- a/public/app/features/dashboard-scene/utils/clone.ts
+++ b/public/app/features/dashboard-scene/utils/clone.ts
@@ -1,3 +1,5 @@
+import { SceneObject } from '@grafana/scenes';
+
const CLONE_KEY = '-clone-';
const CLONE_SEPARATOR = '/';
@@ -71,3 +73,12 @@ export function joinCloneKeys(...keys: string[]): string {
export function containsCloneKey(key: string): boolean {
return key.includes(CLONE_KEY);
}
+
+/**
+ * Useful hook for checking of a scene is a clone
+ * @param scene
+ */
+export function useIsClone(scene: SceneObject): boolean {
+ const { key } = scene.useState();
+ return isClonedKey(key!);
+}
diff --git a/public/app/features/dashboard-scene/utils/utils.ts b/public/app/features/dashboard-scene/utils/utils.ts
index f22210dd3d2..33321ca235b 100644
--- a/public/app/features/dashboard-scene/utils/utils.ts
+++ b/public/app/features/dashboard-scene/utils/utils.ts
@@ -7,18 +7,22 @@ import {
SceneDataTransformer,
sceneGraph,
SceneObject,
+ SceneObjectState,
SceneQueryRunner,
VizPanel,
VizPanelMenu,
} from '@grafana/scenes';
+import { useElementSelection, UseElementSelectionResult } from '@grafana/ui';
import { initialIntervalVariableModelState } from 'app/features/variables/interval/reducer';
import { DashboardDatasourceBehaviour } from '../scene/DashboardDatasourceBehaviour';
-import { DashboardScene } from '../scene/DashboardScene';
+import { DashboardScene, DashboardSceneState } from '../scene/DashboardScene';
import { LibraryPanelBehavior } from '../scene/LibraryPanelBehavior';
import { VizPanelLinks, VizPanelLinksMenu } from '../scene/PanelLinks';
import { panelMenuBehavior } from '../scene/PanelMenuBehavior';
import { DashboardGridItem } from '../scene/layout-default/DashboardGridItem';
+import { ResponsiveGridItem } from '../scene/layout-responsive-grid/ResponsiveGridItem';
+import { RowItem } from '../scene/layout-rows/RowItem';
import { setDashboardPanelContext } from '../scene/setDashboardPanelContext';
import { DashboardLayoutManager, isDashboardLayoutManager } from '../scene/types/DashboardLayoutManager';
@@ -437,3 +441,42 @@ export function getLayoutManagerFor(sceneObject: SceneObject): DashboardLayoutMa
export function getGridItemKeyForPanelId(panelId: number): string {
return `grid-item-${panelId}`;
}
+
+export function useDashboard(scene: SceneObject): DashboardScene {
+ return getDashboardSceneFor(scene);
+}
+
+export function useDashboardState(
+ scene: SceneObject
+): DashboardSceneState & { isEditing: boolean; showHiddenElements: boolean } {
+ const dashboard = useDashboard(scene);
+ const state = dashboard.useState();
+
+ return {
+ ...state,
+ isEditing: !!state.isEditing,
+ showHiddenElements: !!(state.isEditing && state.showHiddenElements),
+ };
+}
+
+export function useIsConditionallyHidden(scene: RowItem | ResponsiveGridItem): boolean {
+ const { conditionalRendering } = scene.useState();
+
+ return !(conditionalRendering?.evaluate() ?? true);
+}
+
+export function useElementSelectionScene(scene: SceneObject): UseElementSelectionResult {
+ const { key } = scene.useState();
+
+ return useElementSelection(key);
+}
+
+export function useInterpolatedTitle(scene: SceneObject): string {
+ const { title } = scene.useState();
+
+ if (!title) {
+ return '';
+ }
+
+ return sceneGraph.interpolate(scene, title, undefined, 'text');
+}
diff --git a/public/locales/en-US/grafana.json b/public/locales/en-US/grafana.json
index 95e6fe9744d..3d1bb21e1d3 100644
--- a/public/locales/en-US/grafana.json
+++ b/public/locales/en-US/grafana.json
@@ -1020,6 +1020,46 @@
"redirect-link": "List in Grafana Alerting",
"subtitle": "Alert rules related to this dashboard"
},
+ "conditional-rendering": {
+ "data": {
+ "disable": "Disable",
+ "enable": "Enable",
+ "label": "Data"
+ },
+ "group": {
+ "add": {
+ "button": "Add condition based on",
+ "data": "Data",
+ "interval": "Interval",
+ "variable": "Variable value"
+ },
+ "condition": {
+ "label": "Evaluate conditions",
+ "meet-all": "Meet all",
+ "meet-any": "Meet any"
+ },
+ "label": "Group"
+ },
+ "interval": {
+ "input-label": "Value",
+ "invalid-message": "Invalid interval",
+ "label": "Time range interval"
+ },
+ "shared": {
+ "delete-condition": "Delete Condition"
+ },
+ "title": "Conditional rendering options",
+ "variable": {
+ "label": "Variable",
+ "operator": {
+ "equals": "Equals",
+ "not-equal": "Not equal"
+ },
+ "select-operator": "Operator",
+ "select-variable": "Select variable",
+ "value-input": "Value"
+ }
+ },
"default-layout": {
"description": "Manually size and position panels",
"item-options": {
@@ -1194,16 +1234,6 @@
},
"responsive-layout": {
"description": "Automatically positions panels into a grid.",
- "item-options": {
- "hide-no-data": "Hide when no data",
- "repeat": {
- "variable": {
- "description": "Repeat this panel for each value in the selected variable. This is not visible while in edit mode. You need to go back to dashboard and then update the variable or reload the dashboard.",
- "title": "Repeat by variable"
- }
- },
- "title": "Layout options"
- },
"name": "Auto",
"options": {
"columns": "Columns",