diff --git a/src/plugins/dashboard/public/dashboard_container/component/grid/dashboard_grid.tsx b/src/plugins/dashboard/public/dashboard_container/component/grid/dashboard_grid.tsx index 0dbfb3a3e87141..aad7c2ea2dd3c4 100644 --- a/src/plugins/dashboard/public/dashboard_container/component/grid/dashboard_grid.tsx +++ b/src/plugins/dashboard/public/dashboard_container/component/grid/dashboard_grid.tsx @@ -6,22 +6,19 @@ * Side Public License, v 1. */ -import 'react-resizable/css/styles.css'; import 'react-grid-layout/css/styles.css'; +import 'react-resizable/css/styles.css'; -import { pick } from 'lodash'; +import { ReactEmbeddableRenderer, ViewMode } from '@kbn/embeddable-plugin/public'; +import { GridLayout, GridLayoutData, GridPanelData } from '@kbn/grid-layout'; import classNames from 'classnames'; -import React, { useState, useMemo, useCallback, useEffect } from 'react'; -import { Layout, Responsive as ResponsiveReactGridLayout } from 'react-grid-layout'; - -import { ViewMode } from '@kbn/embeddable-plugin/public'; - -import { DashboardPanelState } from '../../../../common'; -import { DashboardGridItem } from './dashboard_grid_item'; -import { useDashboardGridSettings } from './use_dashboard_grid_settings'; +import React from 'react'; +import { + DASHBOARD_GRID_COLUMN_COUNT, + DASHBOARD_GRID_HEIGHT, + DASHBOARD_MARGIN_SIZE, +} from '../../../dashboard_constants'; import { useDashboardContainer } from '../../embeddable/dashboard_container'; -import { getPanelLayoutsAreEqual } from '../../state/diffing/dashboard_diffing_utils'; -import { DASHBOARD_GRID_HEIGHT, DASHBOARD_MARGIN_SIZE } from '../../../dashboard_constants'; export const DashboardGrid = ({ viewportWidth }: { viewportWidth: number }) => { const dashboard = useDashboardContainer(); @@ -29,108 +26,66 @@ export const DashboardGrid = ({ viewportWidth }: { viewportWidth: number }) => { const viewMode = dashboard.select((state) => state.explicitInput.viewMode); const useMargins = dashboard.select((state) => state.explicitInput.useMargins); const expandedPanelId = dashboard.select((state) => state.componentState.expandedPanelId); - const focusedPanelId = dashboard.select((state) => state.componentState.focusedPanelId); - const animatePanelTransforms = dashboard.select( - (state) => state.componentState.animatePanelTransforms - ); - - /** - * Track panel maximized state delayed by one tick and use it to prevent - * panel sliding animations on maximize and minimize. - */ - const [delayedIsPanelExpanded, setDelayedIsPanelMaximized] = useState(false); - useEffect(() => { - if (expandedPanelId) { - setDelayedIsPanelMaximized(true); - } else { - setTimeout(() => setDelayedIsPanelMaximized(false), 0); - } - }, [expandedPanelId]); - - const panelsInOrder: string[] = useMemo(() => { - return Object.keys(panels).sort((embeddableIdA, embeddableIdB) => { - const panelA = panels[embeddableIdA]; - const panelB = panels[embeddableIdB]; - - // need to manually sort the panels by position because we want the panels to be collapsed from the left to the - // right when switching to the single column layout, but RGL sorts by ID which can cause unexpected behaviour between - // by-reference and by-value panels + we want the HTML order to align with this in the multi-panel view - if (panelA.gridData.y === panelB.gridData.y) { - return panelA.gridData.x - panelB.gridData.x; - } else { - return panelA.gridData.y - panelB.gridData.y; - } - }); - }, [panels]); - - const panelComponents = useMemo(() => { - return panelsInOrder.map((embeddableId, index) => { - const type = panels[embeddableId].type; - return ( - - ); - }); - }, [expandedPanelId, panels, panelsInOrder, focusedPanelId]); - - const onLayoutChange = useCallback( - (newLayout: Array) => { - if (viewMode !== ViewMode.EDIT) return; - - const updatedPanels: { [key: string]: DashboardPanelState } = newLayout.reduce( - (updatedPanelsAcc, panelLayout) => { - updatedPanelsAcc[panelLayout.i] = { - ...panels[panelLayout.i], - gridData: pick(panelLayout, ['x', 'y', 'w', 'h', 'i']), - }; - return updatedPanelsAcc; - }, - {} as { [key: string]: DashboardPanelState } - ); - if (!getPanelLayoutsAreEqual(panels, updatedPanels)) { - dashboard.dispatch.setPanels(updatedPanels); - } - }, - [dashboard, panels, viewMode] - ); const classes = classNames({ 'dshLayout-withoutMargins': !useMargins, 'dshLayout--viewing': viewMode === ViewMode.VIEW, 'dshLayout--editing': viewMode !== ViewMode.VIEW, - 'dshLayout--noAnimation': !animatePanelTransforms || delayedIsPanelExpanded, 'dshLayout-isMaximizedPanel': expandedPanelId !== undefined, }); - const { layouts, breakpoints, columns } = useDashboardGridSettings(panelsInOrder); - - // in print mode, dashboard layout is not controlled by React Grid Layout - if (viewMode === ViewMode.PRINT) { - return <>{panelComponents}; - } + const panelProps = { + showBadges: true, + showBorder: useMargins, + showNotifications: true, + showShadow: false, + }; return ( - - {panelComponents} - +
+ { + const layoutPanels = Object.values(panels).reduce((acc, panel) => { + const gridData: GridPanelData = { + id: panel.explicitInput.id, + row: panel.gridData.y, + column: panel.gridData.x, + width: panel.gridData.w, + height: panel.gridData.h, + }; + acc[panel.explicitInput.id] = gridData; + return acc; + }, {} as { [key: string]: GridPanelData }); + const initialLayout: GridLayoutData = [ + { + title: 'DEFAULT DASHBOARD', + isCollapsed: false, + panels: layoutPanels, + }, + ]; + return { + initialLayout, + gridSettings: { + gutterSize: DASHBOARD_MARGIN_SIZE, + rowHeight: DASHBOARD_GRID_HEIGHT, + columnCount: DASHBOARD_GRID_COLUMN_COUNT, + }, + }; + }} + renderPanelContents={(embeddableId) => { + const type = panels[embeddableId].type; + return ( + dashboard} + key={`${type}_${embeddableId}`} + onApiAvailable={(api) => dashboard.registerChildApi(api)} + /> + ); + }} + > +
); };