diff --git a/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap b/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap index bd28bfc354f9f..fd1ad71558aa5 100644 --- a/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap +++ b/packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap @@ -48,6 +48,9 @@ Array [ test , "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": true, "schema": "string", @@ -332,6 +335,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": true, "schema": "string", @@ -589,6 +595,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "timestamp", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "timestamp", "initialWidth": 212, "isSortable": true, @@ -837,6 +846,9 @@ Array [ showColumnTokens={true} />, "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": false, "schema": "string", @@ -1082,6 +1094,9 @@ Array [ showColumnTokens={true} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": false, "schema": "string", @@ -1372,6 +1387,9 @@ Array [ showColumnTokens={true} />, "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": false, "schema": "string", @@ -1655,6 +1673,9 @@ Array [ showColumnTokens={true} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": false, "schema": "string", @@ -1819,6 +1840,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": false, "schema": "string", @@ -1976,6 +2000,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": false, "schema": "string", @@ -2191,6 +2218,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "timestamp", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "timestamp", "initialWidth": 212, "isSortable": true, @@ -2396,6 +2426,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": false, "schema": "string", @@ -2598,6 +2631,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": false, "schema": "string", @@ -2823,6 +2859,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "timestamp", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "timestamp", "initialWidth": 212, "isSortable": true, @@ -3043,6 +3082,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "extension", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "extension", "isSortable": true, "schema": "string", @@ -3262,6 +3304,9 @@ Array [ headerRowHeight={5} />, "displayAsText": "message", + "displayHeaderCellProps": Object { + "className": "unifiedDataTable__headerCell", + }, "id": "message", "isSortable": true, "schema": "string", diff --git a/packages/kbn-unified-data-table/src/components/data_table.scss b/packages/kbn-unified-data-table/src/components/data_table.scss index 6093659d487d6..f530e870665f8 100644 --- a/packages/kbn-unified-data-table/src/components/data_table.scss +++ b/packages/kbn-unified-data-table/src/components/data_table.scss @@ -40,14 +40,6 @@ background: transparent; } - .euiDataGridHeaderCell { - align-items: start; - - .euiPopover[class*='euiDataGridHeaderCell__popover'] { - align-self: center; - } - } - .euiDataGrid--bordersHorizontal .euiDataGridHeader { border-top: none; } @@ -101,6 +93,20 @@ } } +// Custom styles for data grid header cell. +// It can also be inside a portal (outside of `unifiedDataTable__inner`) when dragged. +.unifiedDataTable__headerCell { + align-items: start; + + .euiDataGridHeaderCell__draggableIcon { + padding-block: $euiSizeXS / 2; // to align with a token height + } + + .euiDataGridHeaderCell__button { + margin-block: -$euiSizeXS; // to override Eui value for Density "Expanded" + } +} + .unifiedDataTable__table { flex-grow: 1; flex-shrink: 1; diff --git a/packages/kbn-unified-data-table/src/components/data_table.test.tsx b/packages/kbn-unified-data-table/src/components/data_table.test.tsx index 13304d4661cc0..f440c2845adaa 100644 --- a/packages/kbn-unified-data-table/src/components/data_table.test.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table.test.tsx @@ -1354,5 +1354,49 @@ describe('UnifiedDataTable', () => { }, EXTENDED_JEST_TIMEOUT ); + + it( + 'should have columnVisibility configuration', + async () => { + const component = await getComponent({ + ...getProps(), + columns: ['message'], + canDragAndDropColumns: true, + }); + expect(component.find(EuiDataGrid).last().prop('columnVisibility')).toMatchInlineSnapshot(` + Object { + "canDragAndDropColumns": true, + "setVisibleColumns": [Function], + "visibleColumns": Array [ + "@timestamp", + "message", + ], + } + `); + }, + EXTENDED_JEST_TIMEOUT + ); + + it( + 'should disable drag&drop if Summary is present', + async () => { + const component = await getComponent({ + ...getProps(), + columns: [], + canDragAndDropColumns: true, + }); + expect(component.find(EuiDataGrid).last().prop('columnVisibility')).toMatchInlineSnapshot(` + Object { + "canDragAndDropColumns": false, + "setVisibleColumns": [Function], + "visibleColumns": Array [ + "@timestamp", + "_source", + ], + } + `); + }, + EXTENDED_JEST_TIMEOUT + ); }); }); diff --git a/packages/kbn-unified-data-table/src/components/data_table.tsx b/packages/kbn-unified-data-table/src/components/data_table.tsx index 662c8526dd567..a22ee8317be2f 100644 --- a/packages/kbn-unified-data-table/src/components/data_table.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table.tsx @@ -137,6 +137,10 @@ export interface UnifiedDataTableProps { * Field tokens could be rendered in column header next to the field name. */ showColumnTokens?: boolean; + /** + * Set to true to allow users to drag and drop columns for reordering + */ + canDragAndDropColumns?: boolean; /** * Optional value for providing configuration setting for UnifiedDataTable header row height */ @@ -425,6 +429,7 @@ export const UnifiedDataTable = ({ columns, columnsMeta, showColumnTokens, + canDragAndDropColumns, configHeaderRowHeight, headerRowHeightState, onUpdateHeaderRowHeight, @@ -870,13 +875,20 @@ export const UnifiedDataTable = ({ const schemaDetectors = useMemo(() => getSchemaDetectors(), []); const columnsVisibility = useMemo( () => ({ + canDragAndDropColumns: defaultColumns ? false : canDragAndDropColumns, visibleColumns, setVisibleColumns: (newColumns: string[]) => { const dontModifyColumns = !shouldPrependTimeFieldColumn(newColumns); onSetColumns(newColumns, dontModifyColumns); }, }), - [visibleColumns, onSetColumns, shouldPrependTimeFieldColumn] + [ + visibleColumns, + onSetColumns, + shouldPrependTimeFieldColumn, + canDragAndDropColumns, + defaultColumns, + ] ); const canSetExpandedDoc = Boolean(setExpandedDoc && !!renderDocumentView); diff --git a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx index 985a5db9f2178..8f1503ade8a7c 100644 --- a/packages/kbn-unified-data-table/src/components/data_table_columns.tsx +++ b/packages/kbn-unified-data-table/src/components/data_table_columns.tsx @@ -258,6 +258,7 @@ function buildEuiGridColumn({ }, cellActions, visibleCellActions, + displayHeaderCellProps: { className: 'unifiedDataTable__headerCell' }, }; if (column.id === dataView.timeFieldName) { diff --git a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx index 3b0a2df2582aa..e909d3e256d22 100644 --- a/src/plugins/discover/public/components/discover_grid/discover_grid.tsx +++ b/src/plugins/discover/public/components/discover_grid/discover_grid.tsx @@ -58,6 +58,7 @@ export const DiscoverGrid: React.FC = ({ return ( { await unifiedFieldList.clickFieldListItemAdd('@message'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); expect(await dataGrid.resetColumnWidthExists('@message')).to.be(false); }); it('should show reset width button for absolute width column, and allow resetting to auto width', async () => { await unifiedFieldList.clickFieldListItemAdd('@message'); + await header.waitUntilLoadingHasFinished(); + await discover.waitUntilSearchingHasFinished(); await testResizeColumn('@message'); }); diff --git a/test/functional/services/data_grid.ts b/test/functional/services/data_grid.ts index 07a723857088c..f56b58cfa88f1 100644 --- a/test/functional/services/data_grid.ts +++ b/test/functional/services/data_grid.ts @@ -102,9 +102,38 @@ export class DataGridService extends FtrService { public async resizeColumn(field: string, delta: number) { const header = await this.getHeaderElement(field); const originalWidth = (await header.getSize()).width; - const resizer = await header.findByCssSelector( - this.testSubjects.getCssSelector('dataGridColumnResizer') - ); + + let resizer: WebElementWrapper | undefined; + + if (await this.testSubjects.exists('euiDataGridHeaderDroppable')) { + // if drag & drop is enabled for data grid columns + const headerDraggableColumns = await this.find.allByCssSelector( + '[data-test-subj="euiDataGridHeaderDroppable"] > div' + ); + // searching for a common parent of the field column header and its resizer + const fieldHeader: WebElementWrapper | null | undefined = ( + await Promise.all( + headerDraggableColumns.map(async (column) => { + const hasFieldColumn = + (await column.findAllByCssSelector(`[data-gridcell-column-id="${field}"]`)).length > + 0; + return hasFieldColumn ? column : null; + }) + ) + ).find(Boolean); + + resizer = await fieldHeader?.findByTestSubject('dataGridColumnResizer'); + } else { + // if drag & drop is not enabled for data grid columns + resizer = await header.findByCssSelector( + this.testSubjects.getCssSelector('dataGridColumnResizer') + ); + } + + if (!resizer) { + throw new Error(`Unable to find column resizer for field ${field}`); + } + await this.browser.dragAndDrop({ location: resizer }, { location: { x: delta, y: 0 } }); return { originalWidth, newWidth: (await header.getSize()).width }; }