Dynamic Dashboards: Don't show add controls for repeated tabs and rows (#103674)

This commit is contained in:
Bogdan Matei
2025-04-09 13:02:11 +03:00
committed by GitHub
parent 53d5a57a2d
commit dd45c04463
3 changed files with 26 additions and 3 deletions
@@ -27,7 +27,7 @@ import {
ObjectsReorderedOnCanvasEvent,
} from '../../edit-pane/shared';
import { serializeDefaultGridLayout } from '../../serialization/layoutSerializers/DefaultGridLayoutSerializer';
import { isClonedKey, joinCloneKeys } from '../../utils/clone';
import { isClonedKey, joinCloneKeys, useHasClonedParents } from '../../utils/clone';
import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph';
import {
forceRenderChildren,
@@ -533,8 +533,9 @@ function DefaultGridLayoutManagerRenderer({ model }: SceneComponentProps<Default
const { children } = useSceneObjectState(model.state.grid, { shouldActivateOrKeepAlive: true });
const dashboard = useDashboard(model);
const { isEditing } = dashboard.useState();
const hasClonedParents = useHasClonedParents(model);
const styles = useStyles2(getStyles);
const showCanvasActions = isEditing && config.featureToggles.dashboardNewLayouts;
const showCanvasActions = isEditing && config.featureToggles.dashboardNewLayouts && !hasClonedParents;
// If we are top level layout and we have no children, show empty state
if (model.parent === dashboard && children.length === 0) {
@@ -4,6 +4,7 @@ import { GrafanaTheme2 } from '@grafana/data';
import { LazyLoader, SceneComponentProps, sceneGraph } from '@grafana/scenes';
import { useStyles2 } from '@grafana/ui';
import { useHasClonedParents } from '../../utils/clone';
import { useDashboardState } from '../../utils/utils';
import { CanvasGridAddActions } from '../layouts-shared/CanvasGridAddActions';
@@ -12,6 +13,7 @@ import { AutoGridLayoutManager } from './ResponsiveGridLayoutManager';
export function AutoGridLayoutRenderer({ model }: SceneComponentProps<AutoGridLayout>) {
const { children, isHidden, isLazy } = model.useState();
const hasClonedParents = useHasClonedParents(model);
const styles = useStyles2(getStyles, model.state);
const { layoutOrchestrator, isEditing } = useDashboardState(model);
const layoutManager = sceneGraph.getAncestor(model, AutoGridLayoutManager);
@@ -21,6 +23,8 @@ export function AutoGridLayoutRenderer({ model }: SceneComponentProps<AutoGridLa
return null;
}
const showCanvasActions = !hasClonedParents && isEditing;
return (
<div
className={cx(styles.container, fillScreen && styles.containerFillScreen, isEditing && styles.containerEditing)}
@@ -35,7 +39,7 @@ export function AutoGridLayoutRenderer({ model }: SceneComponentProps<AutoGridLa
<item.Component key={item.state.key} model={item} />
)
)}
{isEditing && <CanvasGridAddActions layoutManager={layoutManager} />}
{showCanvasActions && <CanvasGridAddActions layoutManager={layoutManager} />}
</div>
);
}
@@ -1,5 +1,7 @@
import { SceneObject } from '@grafana/scenes';
import { DashboardScene } from '../scene/DashboardScene';
const CLONE_KEY = '-clone-';
const CLONE_SEPARATOR = '/';
@@ -82,3 +84,19 @@ export function useIsClone(scene: SceneObject): boolean {
const { key } = scene.useState();
return isClonedKey(key!);
}
/**
* Useful hook for checking if a scene is in a clone chain
* @param scene
*/
export function useHasClonedParents(scene: SceneObject): boolean {
if (isClonedKey(scene.state.key!)) {
return true;
}
if (!scene.parent || scene.parent instanceof DashboardScene) {
return false;
}
return useHasClonedParents(scene.parent);
}