Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extracted DiscoverGrid to a package named @kbn/unified-data-table as UnifiedDataTable component #163211

Merged
Merged
Show file tree
Hide file tree
Changes from 55 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
db7065c
Extracted DiscoverGrid to a package named kbn unified-data-table Unif…
YulNaumenko Aug 4, 2023
9c991f4
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Aug 4, 2023
4ab1195
fixed yarn.lock
YulNaumenko Aug 4, 2023
3c84e2d
added more properties to extend grid consumer customization capabilities
YulNaumenko Aug 15, 2023
8a00871
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Aug 16, 2023
1a825a5
fixed tsconfig.json
YulNaumenko Aug 19, 2023
6ff9dfe
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Aug 19, 2023
8f0aa94
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 19, 2023
3b14f39
[CI] Auto-commit changed files from 'node scripts/generate codeowners'
kibanamachine Aug 19, 2023
ba7e877
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Aug 19, 2023
d888e2c
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Aug 19, 2023
1ad1c3c
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 19, 2023
f1ff16f
fixed circular deps
YulNaumenko Aug 19, 2023
52fff64
fixed linting errors
YulNaumenko Aug 19, 2023
cf4c0d5
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 19, 2023
02dfeb5
fixed tests
YulNaumenko Aug 19, 2023
f7c55ab
fixed labels
YulNaumenko Aug 20, 2023
2471b69
naming issue
YulNaumenko Aug 20, 2023
eb87062
fixed tests
YulNaumenko Aug 20, 2023
26a7732
fixed jest tests
YulNaumenko Aug 20, 2023
07201f1
fixed default per page items
YulNaumenko Aug 20, 2023
0f67d47
fixed saved search ftrs
YulNaumenko Aug 20, 2023
a33f11c
renaming
YulNaumenko Aug 20, 2023
5225be7
fixed tests
YulNaumenko Aug 20, 2023
06d8d91
-
YulNaumenko Aug 20, 2023
ad9c313
removed unnecesary changes
YulNaumenko Aug 20, 2023
b2da782
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Aug 20, 2023
1ef4ab2
changed format for setAppState
YulNaumenko Aug 21, 2023
4978aac
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 21, 2023
f8a24cc
fixed perf test
YulNaumenko Aug 22, 2023
e012ad9
fixed linting issues
YulNaumenko Aug 22, 2023
c9402d5
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 22, 2023
9047573
lets make CI green. Moved popularize to belong unified-data-table pac…
YulNaumenko Aug 22, 2023
36025e1
Merge branch 'main' into discover_unified_data_table_package
kibanamachine Aug 22, 2023
1387006
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 22, 2023
6ce4451
fixed failing test
YulNaumenko Aug 22, 2023
b4d3519
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 22, 2023
5cf74b7
Added more unit tests
YulNaumenko Aug 22, 2023
726b265
[CI] Auto-commit changed files from 'node scripts/precommit_hook.js -…
kibanamachine Aug 22, 2023
e3c4c03
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 25, 2023
29c14c9
renamed udtDataTable to unifiedDataTable
YulNaumenko Aug 25, 2023
2fa20e9
Cleanup
YulNaumenko Aug 25, 2023
5be3eaf
added readme, finally...
YulNaumenko Aug 25, 2023
f62c7cf
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 25, 2023
37848f8
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Aug 28, 2023
6a0abe0
fixed code editor component to actually apply the value specified in …
YulNaumenko Aug 28, 2023
0499cdf
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Aug 28, 2023
dbacda5
removed console.log
YulNaumenko Aug 28, 2023
2bed9b8
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 28, 2023
7cca274
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Aug 30, 2023
2ada4f7
Merge branch 'main' into discover_unified_data_table_package
kibanamachine Aug 30, 2023
427a595
Addressed comments from review
YulNaumenko Aug 30, 2023
bae1967
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 30, 2023
300db94
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 31, 2023
26ac059
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 31, 2023
d78ab08
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Aug 31, 2023
33675ef
Merge remote-tracking branch 'upstream/main' into discover_unified_da…
YulNaumenko Sep 1, 2023
0134512
[CI] Auto-commit changed files from 'node scripts/lint_ts_projects --…
kibanamachine Sep 1, 2023
2210d85
fixed tests
YulNaumenko Sep 1, 2023
5f22bb5
cleanup
YulNaumenko Sep 1, 2023
5069afd
fixed types error
YulNaumenko Sep 2, 2023
2bcaa84
Merge branch 'main' into discover_unified_data_table_package
kibanamachine Sep 2, 2023
541c41d
fixed tests
YulNaumenko Sep 2, 2023
5a7067f
fixed tourStep for expandButton
YulNaumenko Sep 2, 2023
e38f5a6
Merge branch 'main' into discover_unified_data_table_package
YulNaumenko Sep 2, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -750,6 +750,7 @@ test/plugin_functional/plugins/ui_settings_plugin @elastic/kibana-core
packages/kbn-ui-shared-deps-npm @elastic/kibana-operations
packages/kbn-ui-shared-deps-src @elastic/kibana-operations
packages/kbn-ui-theme @elastic/kibana-operations
packages/kbn-unified-data-table @elastic/kibana-data-discovery
packages/kbn-unified-field-list @elastic/kibana-data-discovery
examples/unified_field_list_examples @elastic/kibana-data-discovery
src/plugins/unified_histogram @elastic/kibana-data-discovery
Expand Down
3 changes: 2 additions & 1 deletion .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,8 @@
"visualizationUiComponents": "packages/kbn-visualization-ui-components",
"unifiedSearch": "src/plugins/unified_search",
"unifiedFieldList": "packages/kbn-unified-field-list",
"unifiedHistogram": "src/plugins/unified_histogram"
"unifiedHistogram": "src/plugins/unified_histogram",
"unifiedDataTable": "packages/kbn-unified-data-table"
},
"translations": []
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -742,6 +742,7 @@
"@kbn/ui-shared-deps-npm": "link:packages/kbn-ui-shared-deps-npm",
"@kbn/ui-shared-deps-src": "link:packages/kbn-ui-shared-deps-src",
"@kbn/ui-theme": "link:packages/kbn-ui-theme",
"@kbn/unified-data-table": "link:packages/kbn-unified-data-table",
"@kbn/unified-field-list": "link:packages/kbn-unified-field-list",
"@kbn/unified-field-list-examples-plugin": "link:examples/unified_field_list_examples",
"@kbn/unified-histogram-plugin": "link:src/plugins/unified_histogram",
Expand Down
15 changes: 15 additions & 0 deletions packages/kbn-discover-utils/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,18 @@ export interface DataTableRecord {
*/
isAnchor?: boolean;
}

export interface FieldMapping {
filterable?: boolean;
scripted?: boolean;
rowCount?: number;
type: string;
name: string;
displayName?: string;
}

export type DocViewFilterFn = (
mapping: FieldMapping | string | undefined,
value: unknown,
mode: '+' | '-'
) => void;
2 changes: 2 additions & 0 deletions packages/kbn-discover-utils/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ export type {
EsHitRecord,
IgnoredReason,
ShouldShowFieldInTableHandler,
DocViewFilterFn,
FieldMapping,
} from './src/types';
239 changes: 239 additions & 0 deletions packages/kbn-unified-data-table/README.md
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for adding this, it's super helpful!

Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
# @kbn/unified-data-table

This package contains components and services for the unified data table UI (as used in Discover).

## UnifiedDataTable Component
Props description:
| Property | Type | Description |
| :--- | :--- | :--- |
| **ariaLabelledBy** | string | Determines which element labels the grid for ARIA. |
| **className** | (optional) string | Optional class name to apply. |
| **columns** | string[] | Determines ids of the columns which are displayed. |
| **expandedDoc** | (optional) DataTableRecord | If set, the given document is displayed in a flyout. |
| **dataView** | DataView | The used data view. |
| **loadingState** | DataLoadingState | Determines if data is currently loaded. |
| **onFilter** | DocViewFilterFn | Function to add a filter in the grid cell or document flyout. |
| **onResize** | (optional)(colSettings: { columnId: string; width: number }) => void; | Function triggered when a column is resized by the user. |
| **onSetColumns** | (columns: string[], hideTimeColumn: boolean) => void; | Function to set all columns. |
| **onSort** | (optional)(sort: string[][]) => void; | Function to change sorting of the documents, skipped when isSortEnabled is set to false. |
| **rows** | (optional)DataTableRecord[] | Array of documents provided by Elasticsearch. |
| **sampleSize** | number | The max size of the documents returned by Elasticsearch. |
| **setExpandedDoc** | (optional)(doc?: DataTableRecord) => void; | Function to set the expanded document, which is displayed in a flyout. |
| **settings** | (optional)UnifiedDataTableSettings | Grid display settings persisted in Elasticsearch (e.g. column width). |
| **searchDescription** | (optional)string | Search description. |
| **searchTitle** | (optional)string | Search title. |
| **showTimeCol** | boolean | Determines whether the time columns should be displayed (legacy settings). |
| **showFullScreenButton** | (optional)boolean | Determines whether the full screen button should be displayed. |
| **isSortEnabled** | (optional)boolean | Manage user sorting control. |
| **sort** | SortOrder[] | Current sort setting. |
| **useNewFieldsApi** | boolean | How the data is fetched. |
| **isPaginationEnabled** | (optional)boolean | Manage pagination control. |
| **controlColumnIds** | (optional)string[] | List of used control columns (available: 'openDetails', 'select'). |
| **rowHeightState** | (optional)number | Row height from state. |
| **onUpdateRowHeight** | (optional)(rowHeight: number) => void; | Update row height state. |
| **isPlainRecord** | (optional)boolean | Is text base lang mode enabled. |
| **rowsPerPageState** | (optional)number | Current state value for rowsPerPage. |
| **onUpdateRowsPerPage** | (optional)(rowsPerPage: number) => void; | Update rows per page state. |
| **onFieldEdited** | (optional)() => void; | Callback to execute on edit runtime field. |
| **cellActionsTriggerId** | (optional)string | Optional triggerId to retrieve the column cell actions that will override the default ones. |
| **services** | See Required **services** list below | Service dependencies. |
| **renderDocumentView** | (optional)(hit: DataTableRecord,displayedRows: DataTableRecord[],displayedColumns: string[]) => JSX.Element | undefined; | Callback to render DocumentView when the document is expanded. |
| **configRowHeight** | (optional)number | Optional value for providing configuration setting for UnifiedDataTable rows height. |
| **showMultiFields** | (optional)boolean | Optional value for providing configuration setting for enabling to display the complex fields in the table. Default is true. |
| **maxDocFieldsDisplayed** | (optional)number | Optional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50. |
| **externalControlColumns** | (optional)EuiDataGridControlColumn[] | Optional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select. |
| **totalHits** | (optional)number | Number total hits from ES. |
| **onFetchMoreRecords** | (optional)() => void | To fetch more. |
| **externalAdditionalControls** | (optional)React.ReactNode | Optional value for providing the additional controls available in the UnifiedDataTable toolbar to manage it's records or state. UnifiedDataTable includes Columns, Sorting and Bulk Actions. |
| **rowsPerPageOptions** | (optional)number[] | Optional list of number type values to set custom UnifiedDataTable paging options to display the records per page. |
| **renderCustomGridBody** | (optional)(args: EuiDataGridCustomBodyProps) => React.ReactNode; | An optional function called to completely customize and control the rendering of EuiDataGrid's body and cell placement. |
| **trailingControlColumns** | (optional)EuiDataGridControlColumn[] | An optional list of the EuiDataGridControlColumn type for setting trailing control columns standard for EuiDataGrid. |
| **visibleCellActions** | (optional)number | An optional value for a custom number of the visible cell actions in the table. By default is up to 3. |
| **externalCustomRenderers** | (optional)Record<string,(props: EuiDataGridCellValueElementProps) => React.ReactNode>; | An optional settings for a specified fields rendering like links. Applied only for the listed fields rendering. |
| **consumer** | (optional)string | Name of the UnifiedDataTable consumer component or application. |

*Required **services** list:
```
theme: ThemeServiceStart;
fieldFormats: FieldFormatsStart;
uiSettings: IUiSettingsClient;
dataViewFieldEditor: DataViewFieldEditorStart;
toastNotifications: ToastsStart;
storage: Storage;
data: DataPublicPluginStart;
```

Usage example:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe worth to add a note, please use useMemo and useCallback, especially for functions passed in, EuiDataGrid's re-rendering is expensive, and should be omitted where possible


```
// Memoize unified data table to avoid the unnecessary re-renderings
const DataTableMemoized = React.memo(UnifiedDataTable);

// Add memoized component with all needed props
<DataTableMemoized
ariaLabelledBy="timelineDocumentsAriaLabel"
className={'unifiedDataTableTimeline'}
columns={['event.category', 'event.action', 'host.name', 'user.name']}
expandedDoc={expandedDoc as DataTableRecord}
dataView={dataView}
loadingState={isQueryLoading ? DataLoadingState.loading : DataLoadingState.loaded}
onFilter={() => {
// Add logic to refetch the data when the filter by field was added/removed. Refetch data.
}}
onResize={(colSettings: { columnId: string; width: number }) => {
// Update the table state with the new width for the column
}}
onSetColumns={(columns: string[], hideTimeColumn: boolean) => {
// Update table state with the new columns. Refetch data.
}}
onSort={!isTextBasedQuery ? onSort : undefined
// Update table state with the new sorting settings. Refetch data.
}
rows={searchResultRows}
sampleSize={500}
setExpandedDoc={() => {
// Callback function to do the logic when the document is expanded
}}
settings={tableSettings}
showTimeCol={true}
isSortEnabled={true}
sort={sortingColumns}
rowHeightState={3}
onUpdateRowHeight={(rowHeight: number) => {
// Do the state update with the new setting of the row height
}}
isPlainRecord={isTextBasedQuery}
rowsPerPageState={50}
onUpdateRowsPerPage={(rowHeight: number) => {
// Do the state update with the new number of the rows per page
}
onFieldEdited={() =>
// Callback to execute on edit runtime field. Refetch data.
}
cellActionsTriggerId={SecurityCellActionsTrigger.DEFAULT}
services={{
theme,
fieldFormats,
storage,
toastNotifications: toastsService,
uiSettings,
dataViewFieldEditor,
data: dataPluginContract,
}}
visibleCellActions={3}
externalCustomRenderers={{
// Set the record style definition for the specific fields rendering Record<string,(props: EuiDataGridCellValueElementProps) => React.ReactNode>
}}
renderDocumentView={() =>
// Implement similar callback to render the Document flyout
const renderDetailsPanel = useCallback(
() => (
<DetailsPanel
browserFields={browserFields}
handleOnPanelClosed={handleOnPanelClosed}
runtimeMappings={runtimeMappings}
tabType={TimelineTabs.query}
scopeId={timelineId}
isFlyoutView
/>
),
[browserFields, handleOnPanelClosed, runtimeMappings, timelineId]
);
}
externalControlColumns={leadingControlColumns}
externalAdditionalControls={additionalControls}
trailingControlColumns={trailingControlColumns}
renderCustomGridBody={renderCustomGridBody}
rowsPerPageOptions={[10, 30, 40, 100]}
showFullScreenButton={false}
useNewFieldsApi={true}
maxDocFieldsDisplayed={50}
consumer="timeline"
totalHits={
// total number of the documents in the search query result. For example: 1200
}
onFetchMoreRecords={() => {
// Do some data fetch to get more data
}}
configRowHeight={3}
showMultiFields={true}
/>
```

## JsonCodeEditorCommon Component
Props description:
| Property | Type | Description |
| :--- | :--- | :--- |
| **width** | (optional) string or number | Editor component width. |
| **height** | (optional) string or number | Editor component height. |
| **hasLineNumbers** | (optional) boolean | Define if the editor component has line numbers style. |
| **hideCopyButton** | (optional) boolean | Show/hide setting for Copy button. |
| **onEditorDidMount** | (editor: monaco.editor.IStandaloneCodeEditor) => void | Do some logic to update the state with the edotor component value. |

Usage example:

```
<JsonCodeEditorCommon
jsonValue={jsonValue}
width={100}
height={400}
hasLineNumbers={true}
onEditorDidMount={(editorNode: monaco.editor.IStandaloneCodeEditor) => setEditor(editorNode)}
/>

```

## Utils

* `getRowsPerPageOptions(currentRowsPerPage)` - gets list of the table defaults for perPage options.

* `getDisplayedColumns(currentRowsPerPage)` - gets list of the table columns with the logic to define the empty list with _source column.

* `popularizeField(...)` - helper function to define the dataView persistance and save indexPattern update capabilities.

## Hooks

* `useColumns(...)` - this hook define the state update for the columns event handlers and allows to use them for external components outside the UnifiedDataTable.

An example of using hooks for defining event handlers for columns management with setting the consumer specific setAppState:

```
const {
columns: currentColumns,
onAddColumn,
onRemoveColumn,
onMoveColumn,
onSetColumns,
} = useColumns({
capabilities,
defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING),
dataView,
dataViews,
setAppState: stateContainer.appState.update,
useNewFieldsApi,
columns,
sort,
});

// Use onAddColumn, onRemoveColumn handlers in the DocumentView

const renderDocumentView = useCallback(
(hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => (
<DiscoverGridFlyout
dataView={dataView}
hit={hit}
hits={displayedRows}
// if default columns are used, dont make them part of the URL - the context state handling will take care to restore them
columns={displayedColumns}
savedSearchId={savedSearch.id}
onFilter={onAddFilter}
onRemoveColumn={onRemoveColumn}
onAddColumn={onAddColumn}
onClose={() => setExpandedDoc(undefined)}
setExpandedDoc={setExpandedDoc}
query={query}
/>
),
[dataView, onAddColumn, onAddFilter, onRemoveColumn, query, savedSearch.id, setExpandedDoc]
);
```
23 changes: 23 additions & 0 deletions packages/kbn-unified-data-table/__mocks__/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import type { Config } from '@kbn/config';

export type ConfigMock = jest.Mocked<Config>;

const createConfigMock = (): ConfigMock => ({
has: jest.fn(),
get: jest.fn(),
set: jest.fn(),
getFlattenedPaths: jest.fn(),
toRaw: jest.fn(),
});

export const configMock = {
create: createConfigMock,
};
Loading