mirror of
https://github.com/elastic/kibana.git
synced 2025-06-27 18:51:07 -04:00
Closes https://github.com/elastic/kibana/issues/216096 ## Summary This PR accomplishes two main things: 1. It flattens out how grid elements are rendered, which means that embeddables no longer re-mount when dragged between sections and 2. It allows panels and sections to be "intermixed" on a **single** level (i.e. you can only drop a section header between panels if they are **not** in a section) Since this was a **major** rewrite of the grid layout logic, I also took some time to clean up the code - this includes removing `proposedGridLayout$` (since this added two sources of truth, which was causing issues with the DOM becoming out-of-sync with the layout object; however, this also caused https://github.com/elastic/kibana/issues/220309) and unifying on the use of "section" rather than "row" (since it was confusing that we were using "row" for both the grid row number and the section ID). https://github.com/user-attachments/assets/c5d9aa97-5b14-4f4c-aacf-74055c7d9c33 > [!NOTE] > Reminder that, since collapsible sections aren't available in Dashboard yet, you must test this PR in the `grid` example app (by running Kibana with `yarn start --run-examples`). ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/src/platform/packages/shared/kbn-i18n/README.md) - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process) --------- Co-authored-by: mbondyra <marta.bondyra@elastic.co> Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Marta Bondyra <4283304+mbondyra@users.noreply.github.com>
90 lines
2.8 KiB
TypeScript
90 lines
2.8 KiB
TypeScript
/*
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
|
* or more contributor license agreements. Licensed under the "Elastic License
|
|
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
|
|
* Public License v 1"; you may not use this file except in compliance with, at
|
|
* your election, the "Elastic License 2.0", the "GNU Affero General Public
|
|
* License v3.0 only", or the "Server Side Public License, v 1".
|
|
*/
|
|
|
|
import { GridLayoutData, GridSectionData } from '@kbn/grid-layout';
|
|
import { MockedDashboardPanelMap, MockedDashboardSectionMap } from './types';
|
|
|
|
export const gridLayoutToDashboardPanelMap = (
|
|
panelState: MockedDashboardPanelMap,
|
|
layout: GridLayoutData
|
|
): { panels: MockedDashboardPanelMap; sections: MockedDashboardSectionMap } => {
|
|
const panels: MockedDashboardPanelMap = {};
|
|
const sections: MockedDashboardSectionMap = {};
|
|
Object.entries(layout).forEach(([widgetId, widget]) => {
|
|
if (widget.type === 'panel') {
|
|
const panelGridData = widget;
|
|
panels[panelGridData.id] = {
|
|
...panelState[panelGridData.id],
|
|
gridData: {
|
|
i: panelGridData.id,
|
|
y: panelGridData.row,
|
|
x: panelGridData.column,
|
|
w: panelGridData.width,
|
|
h: panelGridData.height,
|
|
},
|
|
};
|
|
} else {
|
|
const { panels: rowPanels, type, isCollapsed, row, ...rest } = widget; // drop panels and type
|
|
sections[widgetId] = { ...rest, y: row, collapsed: isCollapsed };
|
|
Object.values(rowPanels).forEach((panelGridData) => {
|
|
panels[panelGridData.id] = {
|
|
...panelState[panelGridData.id],
|
|
gridData: {
|
|
i: panelGridData.id,
|
|
y: panelGridData.row,
|
|
x: panelGridData.column,
|
|
w: panelGridData.width,
|
|
h: panelGridData.height,
|
|
section: widgetId,
|
|
},
|
|
};
|
|
});
|
|
}
|
|
});
|
|
|
|
return { panels, sections };
|
|
};
|
|
|
|
export const dashboardInputToGridLayout = ({
|
|
panels,
|
|
sections,
|
|
}: {
|
|
panels: MockedDashboardPanelMap;
|
|
sections: MockedDashboardSectionMap;
|
|
}): GridLayoutData => {
|
|
const layout: GridLayoutData = {};
|
|
Object.values(sections).forEach((row) => {
|
|
const { collapsed, y, ...rest } = row;
|
|
layout[row.id] = {
|
|
...rest,
|
|
type: 'section',
|
|
row: y,
|
|
panels: {},
|
|
isCollapsed: collapsed,
|
|
};
|
|
});
|
|
|
|
Object.keys(panels).forEach((panelId) => {
|
|
const gridData = panels[panelId].gridData;
|
|
const panelData = {
|
|
id: panelId,
|
|
row: gridData.y,
|
|
column: gridData.x,
|
|
width: gridData.w,
|
|
height: gridData.h,
|
|
};
|
|
if (gridData.section) {
|
|
(layout[gridData.section] as GridSectionData).panels[panelId] = panelData;
|
|
} else {
|
|
layout[panelId] = { type: 'panel', ...panelData };
|
|
}
|
|
});
|
|
|
|
return layout;
|
|
};
|