From f1eac34b54bceb70e2bca5454360b006cf3a0c77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 6 Feb 2025 15:30:54 +0100 Subject: [PATCH] Dashboard: Simpify is empty handling (#100189) * Dashboard: Simpify is empty handling * remove unused imports * Update * Update * Update * add code for other layouts --------- Co-authored-by: Victor Marin --- .../dashboard-scene/scene/DashboardScene.tsx | 2 -- .../scene/DashboardSceneRenderer.tsx | 6 +----- .../DefaultGridLayoutManager.tsx | 13 ++++++++++++ .../ResponsiveGridLayoutManager.tsx | 20 ++++++++++++++++++- .../scene/layout-rows/RowsLayoutManager.tsx | 10 ++++++++++ .../transformSaveModelSchemaV2ToScene.ts | 17 +--------------- .../transformSaveModelToScene.ts | 17 +--------------- 7 files changed, 45 insertions(+), 40 deletions(-) diff --git a/public/app/features/dashboard-scene/scene/DashboardScene.tsx b/public/app/features/dashboard-scene/scene/DashboardScene.tsx index 29c9380039c..14f289bf559 100644 --- a/public/app/features/dashboard-scene/scene/DashboardScene.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardScene.tsx @@ -128,8 +128,6 @@ export interface DashboardSceneState extends SceneObjectState { editPanel?: PanelEditor; /** Scene object that handles the current drawer or modal */ overlay?: SceneObject; - /** The dashboard doesn't have panels */ - isEmpty?: boolean; /** Kiosk mode */ kioskMode?: KioskMode; /** Share view */ diff --git a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx index 794cbe2b2d8..e30068924e7 100644 --- a/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx +++ b/public/app/features/dashboard-scene/scene/DashboardSceneRenderer.tsx @@ -5,7 +5,6 @@ import { PageLayoutType } from '@grafana/data'; import { SceneComponentProps } from '@grafana/scenes'; import { Page } from 'app/core/components/Page/Page'; import { getNavModel } from 'app/core/selectors/navModel'; -import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; import { useSelector } from 'app/types'; import { DashboardEditPaneSplitter } from '../edit-pane/DashboardEditPaneSplitter'; @@ -15,7 +14,7 @@ import { PanelSearchLayout } from './PanelSearchLayout'; import { DashboardAngularDeprecationBanner } from './angular/DashboardAngularDeprecationBanner'; export function DashboardSceneRenderer({ model }: SceneComponentProps) { - const { controls, overlay, editview, editPanel, isEmpty, viewPanelScene, panelSearch, panelsPerRow, isEditing } = + const { controls, overlay, editview, editPanel, viewPanelScene, panelSearch, panelsPerRow, isEditing } = model.useState(); const { type } = useParams(); const location = useLocation(); @@ -56,9 +55,6 @@ export function DashboardSceneRenderer({ model }: SceneComponentProps - {isEmpty && ( - - )} ); diff --git a/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx index c7389618108..a1416c5deb0 100644 --- a/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-default/DefaultGridLayoutManager.tsx @@ -9,9 +9,11 @@ import { sceneUtils, SceneComponentProps, SceneGridItemLike, + useSceneObjectState, } from '@grafana/scenes'; import { GRID_COLUMN_COUNT } from 'app/core/constants'; import { t } from 'app/core/internationalization'; +import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; import { isClonedKey, joinCloneKeys } from '../../utils/clone'; import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph'; @@ -22,6 +24,7 @@ import { NEW_PANEL_WIDTH, getVizPanelKeyForPanelId, getGridItemKeyForPanelId, + getDashboardSceneFor, } from '../../utils/utils'; import { DashboardLayoutManager } from '../types/DashboardLayoutManager'; @@ -447,6 +450,16 @@ export class DefaultGridLayoutManager } public static Component = ({ model }: SceneComponentProps) => { + const { children } = useSceneObjectState(model.state.grid, { shouldActivateOrKeepAlive: true }); + const dashboard = getDashboardSceneFor(model); + + // If we are top level layout and have no children, show empty state + if (model.parent === dashboard && children.length === 0) { + return ( + + ); + } + return ; }; } diff --git a/public/app/features/dashboard-scene/scene/layout-responsive-grid/ResponsiveGridLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-responsive-grid/ResponsiveGridLayoutManager.tsx index 91fcbec0a48..f936d8617eb 100644 --- a/public/app/features/dashboard-scene/scene/layout-responsive-grid/ResponsiveGridLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-responsive-grid/ResponsiveGridLayoutManager.tsx @@ -1,8 +1,16 @@ import { SelectableValue } from '@grafana/data'; -import { SceneComponentProps, SceneCSSGridLayout, SceneObjectBase, SceneObjectState, VizPanel } from '@grafana/scenes'; +import { + SceneComponentProps, + SceneCSSGridLayout, + SceneObjectBase, + SceneObjectState, + useSceneObjectState, + VizPanel, +} from '@grafana/scenes'; import { Select } from '@grafana/ui'; import { t } from 'app/core/internationalization'; import { OptionsPaneItemDescriptor } from 'app/features/dashboard/components/PanelEditor/OptionsPaneItemDescriptor'; +import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; import { dashboardSceneGraph } from '../../utils/dashboardSceneGraph'; import { getDashboardSceneFor, getGridItemKeyForPanelId, getVizPanelKeyForPanelId } from '../../utils/utils'; @@ -140,6 +148,16 @@ export class ResponsiveGridLayoutManager public activateRepeaters(): void {} public static Component = ({ model }: SceneComponentProps) => { + const { children } = useSceneObjectState(model.state.layout, { shouldActivateOrKeepAlive: true }); + const dashboard = getDashboardSceneFor(model); + + // If we are top level layout and have no children, show empty state + if (model.parent === dashboard && children.length === 0) { + return ( + + ); + } + return ; }; } diff --git a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx index dc9154d3b2b..1aafc0adeb2 100644 --- a/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx +++ b/public/app/features/dashboard-scene/scene/layout-rows/RowsLayoutManager.tsx @@ -12,8 +12,10 @@ import { } from '@grafana/scenes'; import { useStyles2 } from '@grafana/ui'; import { t } from 'app/core/internationalization'; +import DashboardEmpty from 'app/features/dashboard/dashgrid/DashboardEmpty'; import { isClonedKey } from '../../utils/clone'; +import { getDashboardSceneFor } from '../../utils/utils'; import { DashboardScene } from '../DashboardScene'; import { DashboardGridItem } from '../layout-default/DashboardGridItem'; import { DefaultGridLayoutManager } from '../layout-default/DefaultGridLayoutManager'; @@ -195,6 +197,14 @@ export class RowsLayoutManager extends SceneObjectBase i public static Component = ({ model }: SceneComponentProps) => { const { rows } = model.useState(); const styles = useStyles2(getStyles); + const dashboard = getDashboardSceneFor(model); + + // If we are top level layout and have no children, show empty state + if (model.parent === dashboard && rows.length === 0) { + return ( + + ); + } return (
diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts index 75be7ae3a42..fd82cc7c161 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelSchemaV2ToScene.ts @@ -88,7 +88,7 @@ import { RowRepeaterBehavior } from '../scene/layout-default/RowRepeaterBehavior import { RowActions } from '../scene/layout-default/row-actions/RowActions'; import { setDashboardPanelContext } from '../scene/setDashboardPanelContext'; import { preserveDashboardSceneStateInLocalStorage } from '../utils/dashboardSessionState'; -import { getDashboardSceneFor, getIntervalsFromQueryString, getVizPanelKeyForPanelId } from '../utils/utils'; +import { getIntervalsFromQueryString, getVizPanelKeyForPanelId } from '../utils/utils'; import { GRID_ROW_HEIGHT } from './const'; import { SnapshotVariable } from './custom-variables/SnapshotVariable'; @@ -181,7 +181,6 @@ export function transformSaveModelSchemaV2ToScene(dto: DashboardWithAccessInfo { - if (n.children.length !== p.children.length || n.children !== p.children) { - getDashboardSceneFor(grid).setState({ isEmpty: n.children.length === 0 }); - } - }); - - return () => { - sub.unsubscribe(); - }; -} - function getPanelDataSource(panel: PanelKind): DataSourceRef | undefined { if (!panel.spec.data?.spec.queries?.length) { return undefined; diff --git a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts index 77960f558ce..b5ca18ea717 100644 --- a/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts +++ b/public/app/features/dashboard-scene/serialization/transformSaveModelToScene.ts @@ -50,7 +50,7 @@ import { setDashboardPanelContext } from '../scene/setDashboardPanelContext'; import { createPanelDataProvider } from '../utils/createPanelDataProvider'; import { preserveDashboardSceneStateInLocalStorage } from '../utils/dashboardSessionState'; import { DashboardInteractions } from '../utils/interactions'; -import { getDashboardSceneFor, getVizPanelKeyForPanelId } from '../utils/utils'; +import { getVizPanelKeyForPanelId } from '../utils/utils'; import { createVariablesForDashboard, createVariablesForSnapshot } from '../utils/variables'; import { getAngularPanelMigrationHandler } from './angularMigration'; @@ -267,7 +267,6 @@ export function createDashboardSceneFromDashboardModel(oldModel: DashboardModel, grid: new SceneGridLayout({ isLazy: !(dto.preload || contextSrv.user.authenticatedBy === 'render'), children: createSceneObjectsForPanels(oldModel.panels), - $behaviors: [trackIfEmpty], }), }), $timeRange: new SceneTimeRange({ @@ -426,20 +425,6 @@ export const convertOldSnapshotToScenesSnapshot = (panel: PanelModel) => { } }; -function trackIfEmpty(grid: SceneGridLayout) { - getDashboardSceneFor(grid).setState({ isEmpty: grid.state.children.length === 0 }); - - const sub = grid.subscribeToState((n, p) => { - if (n.children.length !== p.children.length || n.children !== p.children) { - getDashboardSceneFor(grid).setState({ isEmpty: n.children.length === 0 }); - } - }); - - return () => { - sub.unsubscribe(); - }; -} - function getDashboardInteractionCallback(uid: string, title: string) { return (e: SceneInteractionProfileEvent) => { let interactionType = '';