mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
Extracted DiscoverGrid to a package named @kbn/unified-data-table as UnifiedDataTable component (#163211)
## Summary Current PR includes the next set of changes: 1. Moved `DiscoverGrid` component to a package `@kbn/unified-data-table` and added `@elastic/kibana-data-discovery` as code owners. 2. Changed `@kbn/unified-data-table` package naming for data grid related components and methods to correspond `UnifiedDataTable` instead of `Discover`. 3. Moved hooks `useColumns` and `useRowHeightsOptions` to a package as its logic belongs to `UnifiedDataTable`. 4. Renamed `DiscoverGridContext` to `UnifiedDataTableContext`. 5. Extended `UnifiedDataTable` interface and functionality with the next customization options: - `renderDocumentView?: (displayedRows: DataTableRecord[],displayedColumns: string[]) => JSX.Element | undefined;` - callback to render DocumentView when the document is expanded - `configRowHeight?: number;` - optional value for providing configuration setting for UnifiedDataTable rows height - `showMultiFields?: boolean;` - optional value for providing configuration setting for enabling to display the complex fields in the table. Default is true. - `maxDocFieldsDisplayed?: number;` - optional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50. - `externalControlColumns?: EuiDataGridControlColumn[];` - optional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select. <img width="522" alt="Screenshot 2023-08-22 at 2 26 57 PM" src="d796b9c8
-2fef-4bcc-a3c9-9f5cc6349ab9"> - `externalAdditionalControls?: 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. <img width="673" alt="Screenshot 2023-08-22 at 2 40 28 PM" src="f7ac0c87
-5310-49dd-9084-1ce01ca0f366"> - `rowsPerPageOptions?: number[];` - optional list of number type values to set custom UnifiedDataTable paging options to display the records per page. - `renderCustomGridBody?: (args: EuiDataGridCustomBodyProps) => React.ReactNode;` - An optional function called to completely customize and control the rendering of EuiDataGrid's body and cell placement. <img width="1658" alt="Screenshot 2023-08-22 at 2 50 27 PM" src="14adc18d
-73af-40f5-9859-b3c708e265b1"> - `trailingControlColumns?: EuiDataGridControlColumn[];` - optional list of the `EuiDataGridControlColumn` type for setting trailing control columns standard for `EuiDataGrid`. - `visibleCellActions?: number;` - optional value for a custom number of the visible cell actions in the table <img width="497" alt="Screenshot 2023-08-22 at 2 45 49 PM" src="57ef3ad9
-7401-46bb-9b38-cc8cca2e6a24"> - `externalCustomRenderers?: Record<string,(props: EuiDataGridCellValueElementProps) => React.ReactNode>;` - an optional settings for a specified fields rendering like links. Applied only for the listed fields rendering: <img width="1121" alt="Screenshot 2023-08-22 at 2 51 07 PM" src="77501eae
-3046-4a2c-90e1-2db487c21e2c"> - `consumer` - optional string value for the name of the `UnifiedDataTable` consumer component or application. 6. Extended `UnifiedDataGrid` services with the two additional: `storage: Storage;` `data: DataPublicPluginStart; ` replaced `core: CoreStart;` with `theme: ThemeServiceStart;`, because `core` is used only to get `theme` 7. Replaced `DocumentView` property with `renderDocumentView?: (displayedRows: DataTableRecord[],displayedColumns: string[]) => JSX.Element | undefined;` callback function, which allows not to use `DiscoverGridFlyout` definition for the documents rendering. ``` /** * Document detail view component */ DocumentView?: typeof DiscoverGridFlyout; ``` 8. Removed the next properties from the data table interface, because it was used to render DiscoverGridFlyout: ``` /** * Filters applied by saved search embeddable */ filters?: Filter[]; /** * Query applied by KQL bar or text based editor */ query?: Query | AggregateQuery; /** * Saved search id used for links to single doc and surrounding docs in the flyout */ savedSearchId?: string; ``` 9. Added usage examples and interface description to README file. 10. Changed grid styles naming from `.dscDiscoverGrid*` to `.udtDataTable*` 11. Migrated discover plugin to use `UnifiedDataTable` instead of `DiscoverGrid` Extra changes were needed to avoid the circular dependancies: - moved `DocViewFilterFn` and `FieldMapping` from discover plugin to `packages/kbn-discover-utils/src/types.ts` - added own `export type SortOrder = [string, string];` to avoid deps for saved-search plugin --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
b838cd638a
commit
8fb5a651a0
97 changed files with 2957 additions and 1226 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -751,6 +751,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-doc-viewer @elastic/kibana-data-discovery
|
||||
examples/unified_doc_viewer @elastic/kibana-core
|
||||
src/plugins/unified_doc_viewer @elastic/kibana-data-discovery
|
||||
|
|
|
@ -125,7 +125,8 @@
|
|||
"unifiedDocViewer": ["src/plugins/unified_doc_viewer", "packages/kbn-unified-doc-viewer"],
|
||||
"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": []
|
||||
}
|
||||
|
|
|
@ -743,6 +743,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-doc-viewer": "link:packages/kbn-unified-doc-viewer",
|
||||
"@kbn/unified-doc-viewer-examples": "link:examples/unified_doc_viewer",
|
||||
"@kbn/unified-doc-viewer-plugin": "link:src/plugins/unified_doc_viewer",
|
||||
|
|
241
packages/kbn-unified-data-table/README.md
Normal file
241
packages/kbn-unified-data-table/README.md
Normal file
|
@ -0,0 +1,241 @@
|
|||
# @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. |
|
||||
| **componentsTourSteps** | (optional)Record<string,string> | Optional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour. |
|
||||
|
||||
*Required **services** list:
|
||||
```
|
||||
theme: ThemeServiceStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
uiSettings: IUiSettingsClient;
|
||||
dataViewFieldEditor: DataViewFieldEditorStart;
|
||||
toastNotifications: ToastsStart;
|
||||
storage: Storage;
|
||||
data: DataPublicPluginStart;
|
||||
```
|
||||
|
||||
Usage example:
|
||||
|
||||
```
|
||||
// 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}
|
||||
componentsTourSteps={'expandButton': DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument}
|
||||
/>
|
||||
```
|
||||
|
||||
## 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
packages/kbn-unified-data-table/__mocks__/config.ts
Normal file
23
packages/kbn-unified-data-table/__mocks__/config.ts
Normal file
|
@ -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,
|
||||
};
|
419
packages/kbn-unified-data-table/__mocks__/data_view_complex.ts
Normal file
419
packages/kbn-unified-data-table/__mocks__/data_view_complex.ts
Normal file
|
@ -0,0 +1,419 @@
|
|||
/*
|
||||
* 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 { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
|
||||
const fields = [
|
||||
{
|
||||
count: 0,
|
||||
name: '_id',
|
||||
type: 'string',
|
||||
esTypes: ['_id'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: '_index',
|
||||
type: 'string',
|
||||
esTypes: ['_index'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: '_score',
|
||||
type: 'number',
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: '_source',
|
||||
type: '_source',
|
||||
esTypes: ['_source'],
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: '_type',
|
||||
type: 'string',
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 2,
|
||||
name: 'array_objects.description',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'array_objects.description.keyword',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'array_objects.description',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'array_objects.name',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'array_objects.name.keyword',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'array_objects.name',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'array_tags',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'array_tags.keyword',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'array_tags',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'binary_blob',
|
||||
type: 'unknown',
|
||||
esTypes: ['binary'],
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'bool_enabled',
|
||||
type: 'boolean',
|
||||
esTypes: ['boolean'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'date',
|
||||
type: 'date',
|
||||
esTypes: ['date'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
name: 'date_nanos',
|
||||
type: 'date',
|
||||
esTypes: ['date_nanos'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'flattened_labels',
|
||||
type: 'unknown',
|
||||
esTypes: ['flattened'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'geo_point',
|
||||
type: 'geo_point',
|
||||
esTypes: ['geo_point'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
name: 'geometry',
|
||||
type: 'unknown',
|
||||
esTypes: ['shape'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
name: 'histogram',
|
||||
type: 'histogram',
|
||||
esTypes: ['histogram'],
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'ip_addr',
|
||||
type: 'ip',
|
||||
esTypes: ['ip'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 4,
|
||||
name: 'keyword_key',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'nested_user.first',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
subType: {
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'nested_user.first.keyword',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'nested_user.first',
|
||||
},
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'nested_user.last',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
subType: {
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'nested_user.last.keyword',
|
||||
type: 'string',
|
||||
esTypes: ['keyword'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'nested_user.last',
|
||||
},
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
count: 3,
|
||||
name: 'number_amount',
|
||||
type: 'number',
|
||||
esTypes: ['long'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 3,
|
||||
name: 'number_price',
|
||||
type: 'number',
|
||||
esTypes: ['float'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'object_user.first',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'object_user.last',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'range_time_frame',
|
||||
type: 'date_range',
|
||||
esTypes: ['date_range'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
name: 'rank_features',
|
||||
type: 'unknown',
|
||||
esTypes: ['rank_features'],
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 5,
|
||||
name: 'text_message',
|
||||
type: 'string',
|
||||
esTypes: ['text'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'vector',
|
||||
type: 'unknown',
|
||||
esTypes: ['dense_vector'],
|
||||
scripted: false,
|
||||
searchable: false,
|
||||
aggregatable: false,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'version',
|
||||
type: 'string',
|
||||
esTypes: ['version'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: true,
|
||||
},
|
||||
{
|
||||
count: 1,
|
||||
script: 'return "hi there"',
|
||||
lang: 'painless',
|
||||
name: 'scripted_string',
|
||||
type: 'string',
|
||||
scripted: true,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
{
|
||||
count: 0,
|
||||
name: 'runtime_number',
|
||||
type: 'number',
|
||||
esTypes: ['double'],
|
||||
scripted: false,
|
||||
searchable: true,
|
||||
aggregatable: true,
|
||||
readFromDocValues: false,
|
||||
},
|
||||
] as DataView['fields'];
|
||||
|
||||
export const dataViewComplexMock = buildDataViewMock({
|
||||
name: 'data-view-with-various-field-types',
|
||||
fields,
|
||||
timeFieldName: 'data',
|
||||
});
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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 { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
|
||||
const fields = [
|
||||
{
|
||||
name: '_index',
|
||||
type: 'string',
|
||||
scripted: false,
|
||||
filterable: true,
|
||||
},
|
||||
{
|
||||
name: 'timestamp',
|
||||
displayName: 'timestamp',
|
||||
type: 'date',
|
||||
scripted: false,
|
||||
filterable: true,
|
||||
aggregatable: true,
|
||||
sortable: true,
|
||||
},
|
||||
{
|
||||
name: 'message',
|
||||
displayName: 'message',
|
||||
type: 'string',
|
||||
scripted: false,
|
||||
filterable: false,
|
||||
},
|
||||
{
|
||||
name: 'extension',
|
||||
displayName: 'extension',
|
||||
type: 'string',
|
||||
scripted: false,
|
||||
filterable: true,
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
name: 'bytes',
|
||||
displayName: 'bytes',
|
||||
type: 'number',
|
||||
scripted: false,
|
||||
filterable: true,
|
||||
aggregatable: true,
|
||||
},
|
||||
{
|
||||
name: 'scripted',
|
||||
displayName: 'scripted',
|
||||
type: 'number',
|
||||
scripted: true,
|
||||
filterable: false,
|
||||
},
|
||||
] as DataView['fields'];
|
||||
|
||||
export const dataViewWithTimefieldMock = buildDataViewMock({
|
||||
name: 'index-pattern-with-timefield',
|
||||
fields,
|
||||
timeFieldName: 'timestamp',
|
||||
});
|
45
packages/kbn-unified-data-table/__mocks__/data_views.ts
Normal file
45
packages/kbn-unified-data-table/__mocks__/data_views.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* 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 { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { dataViewComplexMock } from './data_view_complex';
|
||||
import { dataViewWithTimefieldMock } from './data_view_with_timefield';
|
||||
|
||||
export const dataViewMockList = [dataViewMock, dataViewComplexMock, dataViewWithTimefieldMock];
|
||||
|
||||
export function createDataViewsMock() {
|
||||
return {
|
||||
getCache: async () => {
|
||||
return [dataViewMock];
|
||||
},
|
||||
get: async (id: string) => {
|
||||
if (id === 'invalid-data-view-id') {
|
||||
return Promise.reject('Invalid');
|
||||
}
|
||||
const dataView = dataViewMockList.find((dv) => dv.id === id);
|
||||
if (dataView) {
|
||||
return Promise.resolve(dataView);
|
||||
} else {
|
||||
return Promise.reject(`DataView ${id} not found`);
|
||||
}
|
||||
},
|
||||
getDefaultDataView: jest.fn(() => dataViewMock),
|
||||
updateSavedObject: jest.fn(),
|
||||
getIdsWithTitle: jest.fn(() => {
|
||||
return Promise.resolve(dataViewMockList);
|
||||
}),
|
||||
createFilter: jest.fn(),
|
||||
create: jest.fn(),
|
||||
clearInstanceCache: jest.fn(),
|
||||
getFieldsForIndexPattern: jest.fn((dataView) => dataView.fields),
|
||||
refreshFields: jest.fn(),
|
||||
} as unknown as jest.Mocked<DataViewsContract>;
|
||||
}
|
||||
|
||||
export const dataViewsMock = createDataViewsMock();
|
|
@ -0,0 +1,118 @@
|
|||
/*
|
||||
* 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 React, { useState } from 'react';
|
||||
import {
|
||||
EuiCheckbox,
|
||||
EuiButtonIcon,
|
||||
EuiPopover,
|
||||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
EuiPopoverTitle,
|
||||
EuiSpacer,
|
||||
EuiDataGridControlColumn,
|
||||
} from '@elastic/eui';
|
||||
|
||||
const SelectionHeaderCell = () => {
|
||||
return (
|
||||
<div data-test-subj="test-header-control-column-cell">
|
||||
<EuiCheckbox id="selection-toggle" aria-label="Select all rows" onChange={() => null} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SimpleHeaderCell = () => {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
fontSize: '12px',
|
||||
fontWeight: 600,
|
||||
lineHeight: 1.5,
|
||||
minWidth: 0,
|
||||
padding: '4px',
|
||||
width: '100%',
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
}}
|
||||
data-test-subj="test-header-action-cell"
|
||||
>
|
||||
{'Additional Actions'}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const SelectionRowCell = ({ rowIndex }: { rowIndex: number }) => {
|
||||
return (
|
||||
<div data-test-subj="test-body-control-column-cell">
|
||||
<EuiCheckbox
|
||||
id={`${rowIndex}`}
|
||||
aria-label={`Select row test`}
|
||||
checked={false}
|
||||
onChange={() => null}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const TestTrailingColumn = () => {
|
||||
const [isPopoverOpen, setIsPopoverOpen] = useState(false);
|
||||
return (
|
||||
<EuiPopover
|
||||
isOpen={isPopoverOpen}
|
||||
anchorPosition="upCenter"
|
||||
panelPaddingSize="s"
|
||||
button={
|
||||
<EuiButtonIcon
|
||||
aria-label="show actions"
|
||||
iconType="boxesHorizontal"
|
||||
color="text"
|
||||
onClick={() => setIsPopoverOpen(!isPopoverOpen)}
|
||||
/>
|
||||
}
|
||||
data-test-subj="test-trailing-column-popover-button"
|
||||
closePopover={() => setIsPopoverOpen(false)}
|
||||
>
|
||||
<EuiPopoverTitle>{'Actions'}</EuiPopoverTitle>
|
||||
<div style={{ width: 150 }}>
|
||||
<button type="button" onClick={() => {}}>
|
||||
<EuiFlexGroup alignItems="center" component="span" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon aria-label="Pin selected items" iconType="pin" color="text" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>{'Pin'}</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</button>
|
||||
<EuiSpacer size="s" />
|
||||
<button type="button" onClick={() => {}}>
|
||||
<EuiFlexGroup alignItems="center" component="span" gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiButtonIcon aria-label="Delete selected items" iconType="trash" color="text" />
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>{'Delete'}</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
</button>
|
||||
</div>
|
||||
</EuiPopover>
|
||||
);
|
||||
};
|
||||
|
||||
export const testTrailingControlColumns = [
|
||||
{
|
||||
id: 'actions',
|
||||
width: 96,
|
||||
headerCellRender: SimpleHeaderCell,
|
||||
rowCellRender: TestTrailingColumn,
|
||||
},
|
||||
];
|
||||
|
||||
export const testLeadingControlColumn: EuiDataGridControlColumn = {
|
||||
id: 'test-leading-control',
|
||||
headerCellRender: SelectionHeaderCell,
|
||||
rowCellRender: SelectionRowCell,
|
||||
width: 100,
|
||||
};
|
|
@ -0,0 +1,26 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export class LocalStorageMock {
|
||||
private store: Record<string, unknown>;
|
||||
constructor(defaultStore: Record<string, unknown>) {
|
||||
this.store = defaultStore;
|
||||
}
|
||||
clear() {
|
||||
this.store = {};
|
||||
}
|
||||
get(key: string) {
|
||||
return this.store[key] || null;
|
||||
}
|
||||
set(key: string, value: unknown) {
|
||||
this.store[key] = String(value);
|
||||
}
|
||||
remove(key: string) {
|
||||
delete this.store[key];
|
||||
}
|
||||
}
|
116
packages/kbn-unified-data-table/__mocks__/services.ts
Normal file
116
packages/kbn-unified-data-table/__mocks__/services.ts
Normal file
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* 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 { of } from 'rxjs';
|
||||
import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks';
|
||||
import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks';
|
||||
import { chromeServiceMock, coreMock } from '@kbn/core/public/mocks';
|
||||
import { chartPluginMock } from '@kbn/charts-plugin/public/mocks';
|
||||
import { fieldFormatsMock } from '@kbn/field-formats-plugin/common/mocks';
|
||||
import { IUiSettingsClient, ToastsStart } from '@kbn/core/public';
|
||||
import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
import { dataPluginMock } from '@kbn/data-plugin/public/mocks';
|
||||
|
||||
export function createServicesMock() {
|
||||
const expressionsPlugin = expressionsPluginMock.createStartContract();
|
||||
|
||||
expressionsPlugin.run = jest.fn(() =>
|
||||
of({
|
||||
partial: false,
|
||||
result: {
|
||||
rows: [],
|
||||
},
|
||||
})
|
||||
) as unknown as typeof expressionsPlugin.run;
|
||||
|
||||
const corePluginMock = coreMock.createStart();
|
||||
|
||||
const uiSettingsMock: Partial<typeof corePluginMock.uiSettings> = {
|
||||
get: jest.fn(),
|
||||
isDefault: jest.fn((key: string) => {
|
||||
return true;
|
||||
}),
|
||||
};
|
||||
|
||||
corePluginMock.uiSettings = {
|
||||
...corePluginMock.uiSettings,
|
||||
...uiSettingsMock,
|
||||
};
|
||||
|
||||
const theme = {
|
||||
theme$: of({ darkMode: false }),
|
||||
};
|
||||
|
||||
corePluginMock.theme = theme;
|
||||
|
||||
const dataPlugin = dataPluginMock.createStartContract();
|
||||
|
||||
return {
|
||||
core: corePluginMock,
|
||||
charts: chartPluginMock.createSetupContract(),
|
||||
chrome: chromeServiceMock.createStartContract(),
|
||||
history: () => ({
|
||||
location: {
|
||||
search: '',
|
||||
},
|
||||
listen: jest.fn(),
|
||||
}),
|
||||
fieldFormats: fieldFormatsMock,
|
||||
filterManager: jest.fn(),
|
||||
inspector: {
|
||||
open: jest.fn(),
|
||||
},
|
||||
uiActions: uiActionsPluginMock.createStartContract(),
|
||||
uiSettings: uiSettingsMock as IUiSettingsClient,
|
||||
http: {
|
||||
basePath: '/',
|
||||
},
|
||||
dataViewEditor: {
|
||||
openEditor: jest.fn(),
|
||||
userPermissions: {
|
||||
editDataView: jest.fn(() => true),
|
||||
},
|
||||
},
|
||||
dataViewFieldEditor: {
|
||||
openEditor: jest.fn(),
|
||||
userPermissions: {
|
||||
editIndexPattern: jest.fn(() => true),
|
||||
},
|
||||
} as unknown as DataViewFieldEditorStart,
|
||||
theme,
|
||||
storage: {
|
||||
clear: jest.fn(),
|
||||
get: jest.fn(),
|
||||
set: jest.fn(),
|
||||
remove: jest.fn(),
|
||||
},
|
||||
toastNotifications: {
|
||||
addInfo: jest.fn(),
|
||||
addWarning: jest.fn(),
|
||||
addDanger: jest.fn(),
|
||||
addSuccess: jest.fn(),
|
||||
} as unknown as ToastsStart,
|
||||
expressions: expressionsPlugin,
|
||||
savedObjectsTagging: {
|
||||
ui: {
|
||||
getTagIdsFromReferences: jest.fn().mockResolvedValue([]),
|
||||
updateTagsReferences: jest.fn(),
|
||||
},
|
||||
},
|
||||
dataViews: jest.fn(),
|
||||
locator: {
|
||||
useUrl: jest.fn(() => ''),
|
||||
navigate: jest.fn(),
|
||||
getUrl: jest.fn(() => Promise.resolve('')),
|
||||
},
|
||||
contextLocator: { getRedirectUrl: jest.fn(() => '') },
|
||||
singleDocLocator: { getRedirectUrl: jest.fn(() => '') },
|
||||
data: dataPlugin,
|
||||
};
|
||||
}
|
||||
|
||||
export const servicesMock = createServicesMock();
|
|
@ -10,13 +10,13 @@ import type { DataView } from '@kbn/data-views-plugin/public';
|
|||
import { dataViewMock, esHitsMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { dataViewComplexMock } from './data_view_complex';
|
||||
import { esHitsComplex } from './es_hits_complex';
|
||||
import { discoverServiceMock } from './services';
|
||||
import { GridContext } from '../components/discover_grid/discover_grid_context';
|
||||
import { convertValueToString } from '../utils/convert_value_to_string';
|
||||
import { servicesMock } from './services';
|
||||
import { DataTableContext } from '../src/table_context';
|
||||
import { convertValueToString } from '../src/utils/convert_value_to_string';
|
||||
import { buildDataTableRecord } from '@kbn/discover-utils';
|
||||
import type { EsHitRecord } from '@kbn/discover-utils/types';
|
||||
|
||||
const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext => {
|
||||
const buildTableContext = (dataView: DataView, rows: EsHitRecord[]): DataTableContext => {
|
||||
const usedRows = rows.map((row) => {
|
||||
return buildDataTableRecord(row, dataView);
|
||||
});
|
||||
|
@ -34,7 +34,7 @@ const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext
|
|||
convertValueToString({
|
||||
rowIndex,
|
||||
columnId,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
rows: usedRows,
|
||||
dataView,
|
||||
options,
|
||||
|
@ -42,6 +42,6 @@ const buildGridContext = (dataView: DataView, rows: EsHitRecord[]): GridContext
|
|||
};
|
||||
};
|
||||
|
||||
export const discoverGridContextMock = buildGridContext(dataViewMock, esHitsMock);
|
||||
export const dataTableContextMock = buildTableContext(dataViewMock, esHitsMock);
|
||||
|
||||
export const discoverGridContextComplexMock = buildGridContext(dataViewComplexMock, esHitsComplex);
|
||||
export const dataTableContextComplexMock = buildTableContext(dataViewComplexMock, esHitsComplex);
|
21
packages/kbn-unified-data-table/index.ts
Normal file
21
packages/kbn-unified-data-table/index.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { UnifiedDataTable, DataLoadingState } from './src/components/data_table';
|
||||
export type { UnifiedDataTableProps } from './src/components/data_table';
|
||||
export { getDisplayedColumns } from './src/utils/columns';
|
||||
|
||||
export { JSONCodeEditorCommonMemoized } from './src/components/json_code_editor/json_code_editor_common';
|
||||
|
||||
export * from './src/types';
|
||||
export * as columnActions from './src/components/actions/columns';
|
||||
|
||||
export { getRowsPerPageOptions } from './src/utils/rows_per_page';
|
||||
export { popularizeField } from './src/utils/popularize_field';
|
||||
|
||||
export { useColumns } from './src/hooks/use_data_grid_columns';
|
|
@ -6,13 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
/**
|
||||
* User configurable state of data grid, persisted in saved search
|
||||
*/
|
||||
export interface DiscoverGridSettings {
|
||||
columns?: Record<string, DiscoverGridSettingsColumn>;
|
||||
}
|
||||
|
||||
export interface DiscoverGridSettingsColumn {
|
||||
width?: number;
|
||||
}
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../..',
|
||||
roots: ['<rootDir>/packages/kbn-unified-data-table'],
|
||||
};
|
6
packages/kbn-unified-data-table/kibana.jsonc
Normal file
6
packages/kbn-unified-data-table/kibana.jsonc
Normal file
|
@ -0,0 +1,6 @@
|
|||
{
|
||||
"type": "shared-common",
|
||||
"id": "@kbn/unified-data-table",
|
||||
"description": "Contains functionality for the unified data table which can be integrated into apps",
|
||||
"owner": "@elastic/kibana-data-discovery"
|
||||
}
|
10
packages/kbn-unified-data-table/package.json
Normal file
10
packages/kbn-unified-data-table/package.json
Normal file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"name": "@kbn/unified-data-table",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "SSPL-1.0 OR Elastic License 2.0",
|
||||
"sideEffects": [
|
||||
"*.css",
|
||||
"*.scss"
|
||||
]
|
||||
}
|
|
@ -7,15 +7,13 @@
|
|||
*/
|
||||
|
||||
import { getStateColumnActions } from './columns';
|
||||
import { configMock } from '../../../__mocks__/config';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { dataViewsMock } from '../../../__mocks__/data_views';
|
||||
import { Capabilities } from '@kbn/core/types';
|
||||
import { DiscoverAppState } from '../../../application/main/services/discover_app_state_container';
|
||||
import { dataViewsMock } from '../../../__mocks__/data_views';
|
||||
|
||||
function getStateColumnAction(
|
||||
state: DiscoverAppState,
|
||||
setAppState: (state: Partial<DiscoverAppState>) => void
|
||||
state: { columns?: string[]; sort?: string[][] },
|
||||
setAppState: (state: { columns: string[]; sort?: string[][] }) => void
|
||||
) {
|
||||
return getStateColumnActions({
|
||||
capabilities: {
|
||||
|
@ -23,13 +21,13 @@ function getStateColumnAction(
|
|||
save: false,
|
||||
},
|
||||
} as unknown as Capabilities,
|
||||
config: configMock,
|
||||
dataView: dataViewMock,
|
||||
dataViews: dataViewsMock,
|
||||
useNewFieldsApi: true,
|
||||
setAppState,
|
||||
columns: state.columns,
|
||||
sort: state.sort,
|
||||
defaultOrder: 'desc',
|
||||
});
|
||||
}
|
||||
|
|
@ -5,13 +5,10 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { Capabilities, IUiSettingsClient } from '@kbn/core/public';
|
||||
import { DataViewsContract } from '@kbn/data-plugin/public';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { SORT_DEFAULT_ORDER_SETTING } from '@kbn/discover-utils';
|
||||
import { DiscoverAppStateContainer } from '../../../application/main/services/discover_app_state_container';
|
||||
import { GetStateReturn as ContextGetStateReturn } from '../../../application/context/services/context_state';
|
||||
import { popularizeField } from '../../../utils/popularize_field';
|
||||
import { Capabilities } from '@kbn/core/public';
|
||||
import type { DataViewsContract } from '@kbn/data-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { popularizeField } from '../../utils/popularize_field';
|
||||
|
||||
/**
|
||||
* Helper function to provide a fallback to a single _source column if the given array of columns
|
||||
|
@ -57,27 +54,26 @@ export function moveColumn(columns: string[], columnName: string, newIndex: numb
|
|||
|
||||
export function getStateColumnActions({
|
||||
capabilities,
|
||||
config,
|
||||
dataView,
|
||||
dataViews,
|
||||
useNewFieldsApi,
|
||||
setAppState,
|
||||
columns,
|
||||
sort,
|
||||
defaultOrder,
|
||||
}: {
|
||||
capabilities: Capabilities;
|
||||
config: IUiSettingsClient;
|
||||
dataView: DataView;
|
||||
dataViews: DataViewsContract;
|
||||
useNewFieldsApi: boolean;
|
||||
setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState'];
|
||||
setAppState: (state: { columns: string[]; sort?: string[][] }) => void;
|
||||
columns?: string[];
|
||||
sort: string[][] | undefined;
|
||||
defaultOrder: string;
|
||||
}) {
|
||||
function onAddColumn(columnName: string) {
|
||||
popularizeField(dataView, columnName, dataViews, capabilities);
|
||||
const nextColumns = addColumn(columns || [], columnName, useNewFieldsApi);
|
||||
const defaultOrder = config.get(SORT_DEFAULT_ORDER_SETTING);
|
||||
const nextSort = columnName === '_score' && !sort?.length ? [['_score', defaultOrder]] : sort;
|
||||
setAppState({ columns: nextColumns, sort: nextSort });
|
||||
}
|
|
@ -9,8 +9,8 @@
|
|||
import React from 'react';
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
import { discoverGridContextMock } from '../../__mocks__/grid_context';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { dataTableContextMock } from '../../__mocks__/table_context';
|
||||
import { buildCopyColumnNameButton, buildCopyColumnValuesButton } from './build_copy_column_button';
|
||||
|
||||
const execCommandMock = (global.document.execCommand = jest.fn());
|
||||
|
@ -20,7 +20,7 @@ describe('Build a column button to copy to clipboard', () => {
|
|||
it('should copy a column name to clipboard on click', () => {
|
||||
const { label, iconType, onClick } = buildCopyColumnNameButton({
|
||||
columnDisplayName: 'test-field-name',
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
});
|
||||
execCommandMock.mockImplementationOnce(() => true);
|
||||
|
||||
|
@ -49,9 +49,9 @@ describe('Build a column button to copy to clipboard', () => {
|
|||
const { label, iconType, onClick } = buildCopyColumnValuesButton({
|
||||
columnId: 'extension',
|
||||
columnDisplayName: 'custom_extension',
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
rowsCount: 3,
|
||||
valueToStringConverter: discoverGridContextMock.valueToStringConverter,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
});
|
||||
|
||||
const wrapper = mountWithIntl(
|
||||
|
@ -72,8 +72,8 @@ describe('Build a column button to copy to clipboard', () => {
|
|||
} = buildCopyColumnValuesButton({
|
||||
columnId: '_source',
|
||||
columnDisplayName: 'Document',
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
valueToStringConverter: discoverGridContextMock.valueToStringConverter,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 3,
|
||||
});
|
||||
|
||||
|
@ -101,7 +101,7 @@ describe('Build a column button to copy to clipboard', () => {
|
|||
it('should not copy to clipboard on click', () => {
|
||||
const { label, iconType, onClick } = buildCopyColumnNameButton({
|
||||
columnDisplayName: 'test-field-name',
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
});
|
||||
execCommandMock.mockImplementationOnce(() => false);
|
||||
|
|
@ -13,8 +13,8 @@ import type { ToastsStart } from '@kbn/core/public';
|
|||
import {
|
||||
copyColumnValuesToClipboard,
|
||||
copyColumnNameToClipboard,
|
||||
} from '../../utils/copy_value_to_clipboard';
|
||||
import type { ValueToStringConverter } from '../../types';
|
||||
} from '../utils/copy_value_to_clipboard';
|
||||
import type { ValueToStringConverter } from '../types';
|
||||
|
||||
function buildCopyColumnButton({
|
||||
label,
|
||||
|
@ -47,7 +47,7 @@ export function buildCopyColumnNameButton({
|
|||
return buildCopyColumnButton({
|
||||
label: (
|
||||
<FormattedMessage
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
defaultMessage="Copy name"
|
||||
/>
|
||||
),
|
||||
|
@ -72,7 +72,7 @@ export function buildCopyColumnValuesButton({
|
|||
return buildCopyColumnButton({
|
||||
label: (
|
||||
<FormattedMessage
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
defaultMessage="Copy column"
|
||||
/>
|
||||
),
|
|
@ -11,7 +11,7 @@ import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
|||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import React from 'react';
|
||||
import { buildDataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { buildEditFieldButton } from './build_edit_field_button';
|
||||
|
||||
const dataView = buildDataViewMock({
|
||||
|
@ -50,8 +50,7 @@ describe('buildEditFieldButton', () => {
|
|||
it('should return null if the field is not editable', () => {
|
||||
const field = dataView.getFieldByName('unknown_field') as DataViewField;
|
||||
const button = buildEditFieldButton({
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewEditor.userPermissions.editDataView(),
|
||||
hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(),
|
||||
dataView,
|
||||
field,
|
||||
editField: jest.fn(),
|
||||
|
@ -61,12 +60,11 @@ describe('buildEditFieldButton', () => {
|
|||
|
||||
it('should return null if the data view is not editable', () => {
|
||||
jest
|
||||
.spyOn(discoverServiceMock.dataViewEditor.userPermissions, 'editDataView')
|
||||
.spyOn(servicesMock.dataViewEditor.userPermissions, 'editDataView')
|
||||
.mockReturnValueOnce(false);
|
||||
const field = dataView.getFieldByName('bytes') as DataViewField;
|
||||
const button = buildEditFieldButton({
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewEditor.userPermissions.editDataView(),
|
||||
hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(),
|
||||
dataView,
|
||||
field,
|
||||
editField: jest.fn(),
|
||||
|
@ -77,8 +75,7 @@ describe('buildEditFieldButton', () => {
|
|||
it('should return null if passed the _source field', () => {
|
||||
const field = dataView.getFieldByName('_source') as DataViewField;
|
||||
const button = buildEditFieldButton({
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewEditor.userPermissions.editDataView(),
|
||||
hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(),
|
||||
dataView,
|
||||
field,
|
||||
editField: jest.fn(),
|
||||
|
@ -89,8 +86,7 @@ describe('buildEditFieldButton', () => {
|
|||
it('should return EuiListGroupItemProps if the field and data view are editable', () => {
|
||||
const field = dataView.getFieldByName('bytes') as DataViewField;
|
||||
const button = buildEditFieldButton({
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewEditor.userPermissions.editDataView(),
|
||||
hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(),
|
||||
dataView,
|
||||
field,
|
||||
editField: jest.fn(),
|
||||
|
@ -105,7 +101,7 @@ describe('buildEditFieldButton', () => {
|
|||
"iconType": "pencil",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Edit data view field"
|
||||
id="discover.grid.editFieldButton"
|
||||
id="unifiedDataTable.grid.editFieldButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -118,8 +114,7 @@ describe('buildEditFieldButton', () => {
|
|||
const field = dataView.getFieldByName('bytes') as DataViewField;
|
||||
const editField = jest.fn();
|
||||
const buttonProps = buildEditFieldButton({
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewEditor.userPermissions.editDataView(),
|
||||
hasEditDataViewPermission: () => servicesMock.dataViewEditor.userPermissions.editDataView(),
|
||||
dataView,
|
||||
field,
|
||||
editField,
|
|
@ -10,7 +10,7 @@ import { EuiListGroupItemProps } from '@elastic/eui';
|
|||
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import React from 'react';
|
||||
import { getFieldCapabilities } from '../../utils/get_field_capabilities';
|
||||
import { getFieldCapabilities } from '../utils/get_field_capabilities';
|
||||
|
||||
export const buildEditFieldButton = ({
|
||||
hasEditDataViewPermission,
|
||||
|
@ -37,7 +37,10 @@ export const buildEditFieldButton = ({
|
|||
const editFieldButton: EuiListGroupItemProps = {
|
||||
size: 'xs',
|
||||
label: (
|
||||
<FormattedMessage id="discover.grid.editFieldButton" defaultMessage="Edit data view field" />
|
||||
<FormattedMessage
|
||||
id="unifiedDataTable.grid.editFieldButton"
|
||||
defaultMessage="Edit data view field"
|
||||
/>
|
||||
),
|
||||
iconType: 'pencil',
|
||||
iconProps: { size: 'm' },
|
|
@ -1,4 +1,4 @@
|
|||
.dscDiscoverGrid {
|
||||
.unifiedDataTable {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: 100%;
|
||||
|
@ -19,8 +19,8 @@
|
|||
border-right: none;
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__table .euiDataGridRowCell:first-of-type,
|
||||
.dscDiscoverGrid__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type {
|
||||
.unifiedDataTable__table .euiDataGridRowCell:first-of-type,
|
||||
.unifiedDataTable__table .euiDataGrid--headerShade.euiDataGrid--bordersAll .euiDataGridHeaderCell:first-of-type {
|
||||
border-left: none;
|
||||
border-right: none;
|
||||
}
|
||||
|
@ -31,11 +31,11 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__cellValue {
|
||||
.unifiedDataTable__cellValue {
|
||||
font-family: $euiCodeFontFamily;
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__cellPopover {
|
||||
.unifiedDataTable__cellPopover {
|
||||
// Fixes https://github.com/elastic/kibana/issues/145216 in Chrome
|
||||
.lines-content.monaco-editor-background {
|
||||
overflow: unset !important;
|
||||
|
@ -43,7 +43,7 @@
|
|||
}
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__cellPopoverValue {
|
||||
.unifiedDataTable__cellPopoverValue {
|
||||
font-family: $euiCodeFontFamily;
|
||||
font-size: $euiFontSizeS;
|
||||
}
|
||||
|
@ -52,24 +52,32 @@
|
|||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__inner {
|
||||
.unifiedDataTable__inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-wrap: nowrap;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__table {
|
||||
.unifiedDataTable__table {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 1;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.dscTable__flyoutHeader {
|
||||
.unifiedDataTable__footer {
|
||||
flex-shrink: 0;
|
||||
background-color: $euiColorLightShade;
|
||||
padding: $euiSize / 2 $euiSize;
|
||||
margin-top: $euiSize / 4;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.unifiedDataTable__flyoutHeader {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dscTable__flyoutDocumentNavigation {
|
||||
.unifiedDataTable__flyoutDocumentNavigation {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
|
@ -106,11 +114,11 @@
|
|||
width: 100%;
|
||||
}
|
||||
|
||||
.dscFormatSource {
|
||||
.unifiedDataTableFormatSource {
|
||||
@include euiTextTruncate;
|
||||
}
|
||||
|
||||
.dscDiscoverGrid__descriptionListDescription {
|
||||
.unifiedDataTable__descriptionListDescription {
|
||||
word-break: break-all;
|
||||
white-space: normal;
|
||||
|
||||
|
@ -132,7 +140,7 @@
|
|||
|
||||
@include euiBreakpoint('xs', 's', 'm') {
|
||||
// EUI issue to hide 'of' text https://github.com/elastic/eui/issues/4654
|
||||
.dscTable__flyoutDocumentNavigation .euiPagination__compressedText {
|
||||
.unifiedDataTable__flyoutDocumentNavigation .euiPagination__compressedText {
|
||||
display: none;
|
||||
}
|
||||
}
|
|
@ -7,16 +7,23 @@
|
|||
*/
|
||||
import React from 'react';
|
||||
import { ReactWrapper } from 'enzyme';
|
||||
import { EuiCopy } from '@elastic/eui';
|
||||
import {
|
||||
EuiButton,
|
||||
EuiCopy,
|
||||
EuiDataGridCellValueElementProps,
|
||||
EuiDataGridCustomBodyProps,
|
||||
} from '@elastic/eui';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { act } from 'react-dom/test-utils';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { buildDataViewMock, deepMockedFields, esHitsMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { DiscoverGrid, DiscoverGridProps, DataLoadingState } from './discover_grid';
|
||||
import { DataLoadingState, UnifiedDataTable, UnifiedDataTableProps } from './data_table';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { buildDataTableRecord, getDocId } from '@kbn/discover-utils';
|
||||
import type { EsHitRecord } from '@kbn/discover-utils/types';
|
||||
import type { DataTableRecord, EsHitRecord } from '@kbn/discover-utils/types';
|
||||
import { testLeadingControlColumn } from '../../__mocks__/external_control_columns';
|
||||
|
||||
const mockUseDataGridColumnsCellActions = jest.fn((prop: unknown) => []);
|
||||
jest.mock('@kbn/cell-actions', () => ({
|
||||
|
@ -30,8 +37,8 @@ export const dataViewMock = buildDataViewMock({
|
|||
timeFieldName: '@timestamp',
|
||||
});
|
||||
|
||||
function getProps() {
|
||||
const services = discoverServiceMock;
|
||||
function getProps(): UnifiedDataTableProps {
|
||||
const services = servicesMock;
|
||||
services.dataViewFieldEditor.userPermissions.editIndexPattern = jest.fn().mockReturnValue(true);
|
||||
|
||||
return {
|
||||
|
@ -40,9 +47,7 @@ function getProps() {
|
|||
dataView: dataViewMock,
|
||||
loadingState: DataLoadingState.loaded,
|
||||
expandedDoc: undefined,
|
||||
onAddColumn: jest.fn(),
|
||||
onFilter: jest.fn(),
|
||||
onRemoveColumn: jest.fn(),
|
||||
onResize: jest.fn(),
|
||||
onSetColumns: jest.fn(),
|
||||
onSort: jest.fn(),
|
||||
|
@ -55,14 +60,22 @@ function getProps() {
|
|||
showTimeCol: true,
|
||||
sort: [],
|
||||
useNewFieldsApi: true,
|
||||
services,
|
||||
services: {
|
||||
fieldFormats: services.fieldFormats,
|
||||
uiSettings: services.uiSettings,
|
||||
dataViewFieldEditor: services.dataViewFieldEditor,
|
||||
toastNotifications: services.toastNotifications,
|
||||
storage: services.storage as unknown as Storage,
|
||||
data: services.data,
|
||||
theme: services.theme,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async function getComponent(props: DiscoverGridProps = getProps()) {
|
||||
const Proxy = (innerProps: DiscoverGridProps) => (
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGrid {...innerProps} />
|
||||
async function getComponent(props: UnifiedDataTableProps = getProps()) {
|
||||
const Proxy = (innerProps: UnifiedDataTableProps) => (
|
||||
<KibanaContextProvider services={servicesMock}>
|
||||
<UnifiedDataTable {...innerProps} />
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
|
||||
|
@ -74,7 +87,7 @@ async function getComponent(props: DiscoverGridProps = getProps()) {
|
|||
return component;
|
||||
}
|
||||
|
||||
function getSelectedDocNr(component: ReactWrapper<DiscoverGridProps>) {
|
||||
function getSelectedDocNr(component: ReactWrapper<UnifiedDataTableProps>) {
|
||||
const gridSelectionBtn = findTestSubject(component, 'dscGridSelectionBtn');
|
||||
if (!gridSelectionBtn.length) {
|
||||
return 0;
|
||||
|
@ -83,7 +96,7 @@ function getSelectedDocNr(component: ReactWrapper<DiscoverGridProps>) {
|
|||
return Number(selectedNr);
|
||||
}
|
||||
|
||||
function getDisplayedDocNr(component: ReactWrapper<DiscoverGridProps>) {
|
||||
function getDisplayedDocNr(component: ReactWrapper<UnifiedDataTableProps>) {
|
||||
const gridSelectionBtn = findTestSubject(component, 'discoverDocTable');
|
||||
if (!gridSelectionBtn.length) {
|
||||
return 0;
|
||||
|
@ -93,7 +106,7 @@ function getDisplayedDocNr(component: ReactWrapper<DiscoverGridProps>) {
|
|||
}
|
||||
|
||||
async function toggleDocSelection(
|
||||
component: ReactWrapper<DiscoverGridProps>,
|
||||
component: ReactWrapper<UnifiedDataTableProps>,
|
||||
document: EsHitRecord
|
||||
) {
|
||||
act(() => {
|
||||
|
@ -103,13 +116,13 @@ async function toggleDocSelection(
|
|||
component.update();
|
||||
}
|
||||
|
||||
describe('DiscoverGrid', () => {
|
||||
describe('UnifiedDataTable', () => {
|
||||
afterEach(async () => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
describe('Document selection', () => {
|
||||
let component: ReactWrapper<DiscoverGridProps>;
|
||||
let component: ReactWrapper<UnifiedDataTableProps>;
|
||||
beforeEach(async () => {
|
||||
component = await getComponent();
|
||||
});
|
||||
|
@ -287,4 +300,136 @@ describe('DiscoverGrid', () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
|
||||
describe('externalControlColumns', () => {
|
||||
it('should render external leading control columns', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
expandedDoc: {
|
||||
id: 'test',
|
||||
raw: {
|
||||
_index: 'test_i',
|
||||
_id: 'test',
|
||||
},
|
||||
flattened: { test: jest.fn() },
|
||||
},
|
||||
setExpandedDoc: jest.fn(),
|
||||
renderDocumentView: jest.fn(),
|
||||
externalControlColumns: [testLeadingControlColumn],
|
||||
});
|
||||
|
||||
expect(findTestSubject(component, 'docTableExpandToggleColumn').exists()).toBeTruthy();
|
||||
expect(findTestSubject(component, 'test-body-control-column-cell').exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
it('should render provided in renderDocumentView DocumentView on expand clicked', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
expandedDoc: {
|
||||
id: 'test',
|
||||
raw: {
|
||||
_index: 'test_i',
|
||||
_id: 'test',
|
||||
},
|
||||
flattened: { test: jest.fn() },
|
||||
},
|
||||
setExpandedDoc: jest.fn(),
|
||||
renderDocumentView: (
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[]
|
||||
) => <div data-test-subj="test-document-view">{hit.id}</div>,
|
||||
externalControlColumns: [testLeadingControlColumn],
|
||||
});
|
||||
|
||||
findTestSubject(component, 'docTableExpandToggleColumn').first().simulate('click');
|
||||
expect(findTestSubject(component, 'test-document-view').exists()).toBeTruthy();
|
||||
});
|
||||
|
||||
describe('externalAdditionalControls', () => {
|
||||
it('should render external additional toolbar controls', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
columns: ['message'],
|
||||
externalAdditionalControls: <EuiButton data-test-subj="test-additional-control" />,
|
||||
});
|
||||
|
||||
expect(findTestSubject(component, 'test-additional-control').exists()).toBeTruthy();
|
||||
expect(findTestSubject(component, 'dataGridColumnSelectorButton').exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('externalCustomRenderers', () => {
|
||||
it('should render only host column with the custom renderer, message should be rendered with the default cell renderer', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
columns: ['message', 'host'],
|
||||
externalCustomRenderers: {
|
||||
host: (props: EuiDataGridCellValueElementProps) => (
|
||||
<div data-test-subj={`test-renderer-${props.columnId}`}>{props.columnId}</div>
|
||||
),
|
||||
},
|
||||
});
|
||||
|
||||
expect(findTestSubject(component, 'test-renderer-host').exists()).toBeTruthy();
|
||||
expect(findTestSubject(component, 'test-renderer-message').exists()).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderCustomGridBody', () => {
|
||||
it('should render custom grid body for each row', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
columns: ['message', 'host'],
|
||||
trailingControlColumns: [
|
||||
{
|
||||
id: 'row-details',
|
||||
|
||||
// The header cell should be visually hidden, but available to screen readers
|
||||
width: 0,
|
||||
headerCellRender: () => <></>,
|
||||
headerCellProps: { className: 'euiScreenReaderOnly' },
|
||||
|
||||
// The footer cell can be hidden to both visual & SR users, as it does not contain meaningful information
|
||||
footerCellProps: { style: { display: 'none' } },
|
||||
|
||||
// When rendering this custom cell, we'll want to override
|
||||
// the automatic width/heights calculated by EuiDataGrid
|
||||
rowCellRender: jest.fn(),
|
||||
},
|
||||
],
|
||||
renderCustomGridBody: (props: EuiDataGridCustomBodyProps) => (
|
||||
<div data-test-subj="test-renderer-custom-grid-body">
|
||||
<EuiButton />
|
||||
</div>
|
||||
),
|
||||
});
|
||||
|
||||
expect(findTestSubject(component, 'test-renderer-custom-grid-body').exists()).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
describe('componentsTourSteps', () => {
|
||||
it('should render tour step for the first row of leading control column expandButton', async () => {
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
expandedDoc: {
|
||||
id: 'test',
|
||||
raw: {
|
||||
_index: 'test_i',
|
||||
_id: 'test',
|
||||
},
|
||||
flattened: { test: jest.fn() },
|
||||
},
|
||||
setExpandedDoc: jest.fn(),
|
||||
renderDocumentView: jest.fn(),
|
||||
componentsTourSteps: { expandButton: 'test-expand' },
|
||||
});
|
||||
|
||||
const gridExpandBtn = findTestSubject(component, 'docTableExpandToggleColumn').first();
|
||||
const tourStep = gridExpandBtn.getDOMNode().getAttribute('id');
|
||||
expect(tourStep).toEqual('test-expand');
|
||||
});
|
||||
});
|
||||
});
|
|
@ -11,7 +11,8 @@ import classnames from 'classnames';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { of } from 'rxjs';
|
||||
import useObservable from 'react-use/lib/useObservable';
|
||||
import './discover_grid.scss';
|
||||
import './data_table.scss';
|
||||
import type { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
EuiDataGridSorting,
|
||||
EuiDataGrid,
|
||||
|
@ -23,44 +24,42 @@ import {
|
|||
EuiIcon,
|
||||
EuiDataGridRefProps,
|
||||
EuiDataGridInMemory,
|
||||
EuiDataGridControlColumn,
|
||||
EuiDataGridCustomBodyProps,
|
||||
EuiDataGridCellValueElementProps,
|
||||
} from '@elastic/eui';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { SortOrder } from '@kbn/saved-search-plugin/public';
|
||||
import {
|
||||
useDataGridColumnsCellActions,
|
||||
type UseDataGridColumnsCellActionsProps,
|
||||
} from '@kbn/cell-actions';
|
||||
import type { AggregateQuery, Filter, Query } from '@kbn/es-query';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { ToastsStart, IUiSettingsClient, HttpStart, CoreStart } from '@kbn/core/public';
|
||||
import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
import { Serializable } from '@kbn/utility-types';
|
||||
import type { ToastsStart, IUiSettingsClient } from '@kbn/core/public';
|
||||
import type { Serializable } from '@kbn/utility-types';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { getShouldShowFieldHandler } from '@kbn/discover-utils';
|
||||
import {
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
SHOW_MULTIFIELDS,
|
||||
} from '@kbn/discover-utils';
|
||||
import { getShouldShowFieldHandler, DOC_HIDE_TIME_COLUMN_SETTING } from '@kbn/discover-utils';
|
||||
import type { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { ThemeServiceStart } from '@kbn/react-kibana-context-common';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { getSchemaDetectors } from './discover_grid_schema';
|
||||
import { DiscoverGridFlyout } from './discover_grid_flyout';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { getRenderCellValueFn } from './get_render_cell_value';
|
||||
import { DiscoverGridSettings } from './types';
|
||||
import { UnifiedDataTableSettings, ValueToStringConverter } from '../types';
|
||||
import { getDisplayedColumns } from '../utils/columns';
|
||||
import { convertValueToString } from '../utils/convert_value_to_string';
|
||||
import { getRowsPerPageOptions } from '../utils/rows_per_page';
|
||||
import { getRenderCellValueFn } from '../utils/get_render_cell_value';
|
||||
import { getEuiGridColumns, getLeadControlColumns, getVisibleColumns } from './data_table_columns';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
import { getSchemaDetectors } from './data_table_schema';
|
||||
import { DataTableDocumentToolbarBtn } from './data_table_document_selection';
|
||||
import { useRowHeightsOptions } from '../hooks/use_row_heights_options';
|
||||
import {
|
||||
getEuiGridColumns,
|
||||
getLeadControlColumns,
|
||||
getVisibleColumns,
|
||||
} from './discover_grid_columns';
|
||||
import { GRID_STYLE, toolbarVisibility as toolbarVisibilityDefaults } from './constants';
|
||||
import { getDisplayedColumns } from '../../utils/columns';
|
||||
import { DiscoverGridDocumentToolbarBtn } from './discover_grid_document_selection';
|
||||
import { DiscoverGridFooter } from './discover_grid_footer';
|
||||
import type { ValueToStringConverter } from '../../types';
|
||||
import { useRowHeightsOptions } from '../../hooks/use_row_heights_options';
|
||||
import { convertValueToString } from '../../utils/convert_value_to_string';
|
||||
import { getRowsPerPageOptions, getDefaultRowsPerPage } from '../../utils/rows_per_page';
|
||||
DEFAULT_ROWS_PER_PAGE,
|
||||
GRID_STYLE,
|
||||
toolbarVisibility as toolbarVisibilityDefaults,
|
||||
} from '../constants';
|
||||
import { UnifiedDataTableFooter } from './data_table_footer';
|
||||
|
||||
export type SortOrder = [string, string];
|
||||
|
||||
export enum DataLoadingState {
|
||||
loading = 'loading',
|
||||
|
@ -75,7 +74,7 @@ interface SortObj {
|
|||
direction: string;
|
||||
}
|
||||
|
||||
export interface DiscoverGridProps {
|
||||
export interface UnifiedDataTableProps {
|
||||
/**
|
||||
* Determines which element labels the grid for ARIA
|
||||
*/
|
||||
|
@ -85,7 +84,7 @@ export interface DiscoverGridProps {
|
|||
*/
|
||||
className?: string;
|
||||
/**
|
||||
* Determines which columns are displayed
|
||||
* Determines ids of the columns which are displayed
|
||||
*/
|
||||
columns: string[];
|
||||
/**
|
||||
|
@ -100,19 +99,10 @@ export interface DiscoverGridProps {
|
|||
* Determines if data is currently loaded
|
||||
*/
|
||||
loadingState: DataLoadingState;
|
||||
/**
|
||||
* Function used to add a column in the document flyout
|
||||
*/
|
||||
onAddColumn: (column: string) => void;
|
||||
/**
|
||||
* Function to add a filter in the grid cell or document flyout
|
||||
*/
|
||||
onFilter: DocViewFilterFn;
|
||||
/**
|
||||
* Function used in the grid header and flyout to remove a column
|
||||
* @param column
|
||||
*/
|
||||
onRemoveColumn: (column: string) => void;
|
||||
/**
|
||||
* Function triggered when a column is resized by the user
|
||||
*/
|
||||
|
@ -140,13 +130,13 @@ export interface DiscoverGridProps {
|
|||
/**
|
||||
* Grid display settings persisted in Elasticsearch (e.g. column width)
|
||||
*/
|
||||
settings?: DiscoverGridSettings;
|
||||
settings?: UnifiedDataTableSettings;
|
||||
/**
|
||||
* Saved search description
|
||||
* Search description
|
||||
*/
|
||||
searchDescription?: string;
|
||||
/**
|
||||
* Saved search title
|
||||
* Search title
|
||||
*/
|
||||
searchTitle?: string;
|
||||
/**
|
||||
|
@ -201,22 +191,6 @@ export interface DiscoverGridProps {
|
|||
* Callback to execute on edit runtime field
|
||||
*/
|
||||
onFieldEdited?: () => void;
|
||||
/**
|
||||
* Filters applied by saved search embeddable
|
||||
*/
|
||||
filters?: Filter[];
|
||||
/**
|
||||
* Query applied by KQL bar or text based editor
|
||||
*/
|
||||
query?: Query | AggregateQuery;
|
||||
/**
|
||||
* Saved search id used for links to single doc and surrounding docs in the flyout
|
||||
*/
|
||||
savedSearchId?: string;
|
||||
/**
|
||||
* Document detail view component
|
||||
*/
|
||||
DocumentView?: typeof DiscoverGridFlyout;
|
||||
/**
|
||||
* Optional triggerId to retrieve the column cell actions that will override the default ones
|
||||
*/
|
||||
|
@ -225,13 +199,38 @@ export interface DiscoverGridProps {
|
|||
* Service dependencies
|
||||
*/
|
||||
services: {
|
||||
core: CoreStart;
|
||||
theme: ThemeServiceStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
addBasePath: HttpStart['basePath']['prepend'];
|
||||
uiSettings: IUiSettingsClient;
|
||||
dataViewFieldEditor: DataViewFieldEditorStart;
|
||||
toastNotifications: ToastsStart;
|
||||
storage: Storage;
|
||||
data: DataPublicPluginStart;
|
||||
};
|
||||
/**
|
||||
* Callback to render DocumentView when the document is expanded
|
||||
*/
|
||||
renderDocumentView?: (
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[]
|
||||
) => JSX.Element | undefined;
|
||||
/**
|
||||
* Optional value for providing configuration setting for UnifiedDataTable rows height
|
||||
*/
|
||||
configRowHeight?: number;
|
||||
/**
|
||||
* Optional value for providing configuration setting for enabling to display the complex fields in the table. Default is true.
|
||||
*/
|
||||
showMultiFields?: boolean;
|
||||
/**
|
||||
* Optional value for providing configuration setting for maximum number of document fields to display in the table. Default is 50.
|
||||
*/
|
||||
maxDocFieldsDisplayed?: number;
|
||||
/**
|
||||
* Optional value for providing EuiDataGridControlColumn list of the additional leading control columns. UnifiedDataTable includes two control columns: Open Details and Select.
|
||||
*/
|
||||
externalControlColumns?: EuiDataGridControlColumn[];
|
||||
/**
|
||||
* Number total hits from ES
|
||||
*/
|
||||
|
@ -240,24 +239,62 @@ export interface DiscoverGridProps {
|
|||
* To fetch more
|
||||
*/
|
||||
onFetchMoreRecords?: () => void;
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
externalAdditionalControls?: React.ReactNode;
|
||||
/**
|
||||
* Optional list of number type values to set custom UnifiedDataTable paging options to display the records per page.
|
||||
*/
|
||||
rowsPerPageOptions?: number[];
|
||||
/**
|
||||
* An optional function called to completely customize and control the rendering of
|
||||
* EuiDataGrid's body and cell placement. This can be used to, e.g. remove EuiDataGrid's
|
||||
* virtualization library, or roll your own.
|
||||
*
|
||||
* This component is **only** meant as an escape hatch for extremely custom use cases.
|
||||
*
|
||||
* Behind the scenes, this function is treated as a React component,
|
||||
* allowing hooks, context, and other React concepts to be used.
|
||||
* It receives #EuiDataGridCustomBodyProps as its only argument.
|
||||
*/
|
||||
renderCustomGridBody?: (args: EuiDataGridCustomBodyProps) => React.ReactNode;
|
||||
/**
|
||||
* An optional list of the EuiDataGridControlColumn type for setting trailing control columns standard for EuiDataGrid.
|
||||
*/
|
||||
trailingControlColumns?: EuiDataGridControlColumn[];
|
||||
/**
|
||||
* An optional value for a custom number of the visible cell actions in the table. By default is up to 3.
|
||||
**/
|
||||
visibleCellActions?: number;
|
||||
/**
|
||||
* An optional settings for a specified fields rendering like links. Applied only for the listed fields rendering.
|
||||
*/
|
||||
externalCustomRenderers?: Record<
|
||||
string,
|
||||
(props: EuiDataGridCellValueElementProps) => React.ReactNode
|
||||
>;
|
||||
/**
|
||||
* Name of the UnifiedDataTable consumer component or application
|
||||
*/
|
||||
consumer?: string;
|
||||
/**
|
||||
* Optional key/value pairs to set guided onboarding steps ids for a data table components included to guided tour.
|
||||
*/
|
||||
componentsTourSteps?: Record<string, string>;
|
||||
}
|
||||
|
||||
export const EuiDataGridMemoized = React.memo(EuiDataGrid);
|
||||
|
||||
const CONTROL_COLUMN_IDS_DEFAULT = ['openDetails', 'select'];
|
||||
|
||||
export const DiscoverGrid = ({
|
||||
export const UnifiedDataTable = ({
|
||||
ariaLabelledBy,
|
||||
columns,
|
||||
controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT,
|
||||
dataView,
|
||||
loadingState,
|
||||
expandedDoc,
|
||||
onAddColumn,
|
||||
filters,
|
||||
query,
|
||||
savedSearchId,
|
||||
onFilter,
|
||||
onRemoveColumn,
|
||||
onResize,
|
||||
onSetColumns,
|
||||
onSort,
|
||||
|
@ -265,7 +302,6 @@ export const DiscoverGrid = ({
|
|||
sampleSize,
|
||||
searchDescription,
|
||||
searchTitle,
|
||||
setExpandedDoc,
|
||||
settings,
|
||||
showTimeCol,
|
||||
showFullScreenButton = true,
|
||||
|
@ -273,7 +309,6 @@ export const DiscoverGrid = ({
|
|||
useNewFieldsApi,
|
||||
isSortEnabled = true,
|
||||
isPaginationEnabled = true,
|
||||
controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT,
|
||||
cellActionsTriggerId,
|
||||
className,
|
||||
rowHeightState,
|
||||
|
@ -282,13 +317,28 @@ export const DiscoverGrid = ({
|
|||
rowsPerPageState,
|
||||
onUpdateRowsPerPage,
|
||||
onFieldEdited,
|
||||
DocumentView,
|
||||
services,
|
||||
renderCustomGridBody,
|
||||
trailingControlColumns,
|
||||
totalHits,
|
||||
onFetchMoreRecords,
|
||||
}: DiscoverGridProps) => {
|
||||
const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings } = services;
|
||||
const { darkMode } = useObservable(services.core.theme?.theme$ ?? of(themeDefault), themeDefault);
|
||||
renderDocumentView,
|
||||
setExpandedDoc,
|
||||
expandedDoc,
|
||||
configRowHeight,
|
||||
showMultiFields = true,
|
||||
maxDocFieldsDisplayed = 50,
|
||||
externalControlColumns,
|
||||
externalAdditionalControls,
|
||||
rowsPerPageOptions,
|
||||
visibleCellActions,
|
||||
externalCustomRenderers,
|
||||
consumer = 'discover',
|
||||
componentsTourSteps,
|
||||
}: UnifiedDataTableProps) => {
|
||||
const { fieldFormats, toastNotifications, dataViewFieldEditor, uiSettings, storage, data } =
|
||||
services;
|
||||
const { darkMode } = useObservable(services.theme?.theme$ ?? of(themeDefault), themeDefault);
|
||||
const dataGridRef = useRef<EuiDataGridRefProps>(null);
|
||||
const [selectedDocs, setSelectedDocs] = useState<string[]>([]);
|
||||
const [isFilterActive, setIsFilterActive] = useState(false);
|
||||
|
@ -300,7 +350,7 @@ export const DiscoverGrid = ({
|
|||
}
|
||||
const idMap = rows.reduce((map, row) => map.set(row.id, true), new Map());
|
||||
// filter out selected docs that are no longer part of the current data
|
||||
const result = selectedDocs.filter((docId) => idMap.get(docId));
|
||||
const result = selectedDocs.filter((docId) => !!idMap.get(docId));
|
||||
if (result.length === 0 && isFilterActive) {
|
||||
setIsFilterActive(false);
|
||||
}
|
||||
|
@ -336,17 +386,45 @@ export const DiscoverGrid = ({
|
|||
[displayedRows, dataView, fieldFormats]
|
||||
);
|
||||
|
||||
const unifiedDataTableContextValue = useMemo(
|
||||
() => ({
|
||||
expanded: expandedDoc,
|
||||
setExpanded: setExpandedDoc,
|
||||
rows: displayedRows,
|
||||
onFilter,
|
||||
dataView,
|
||||
isDarkMode: darkMode,
|
||||
selectedDocs: usedSelectedDocs,
|
||||
setSelectedDocs: (newSelectedDocs: React.SetStateAction<string[]>) => {
|
||||
setSelectedDocs(newSelectedDocs);
|
||||
if (isFilterActive && newSelectedDocs.length === 0) {
|
||||
setIsFilterActive(false);
|
||||
}
|
||||
},
|
||||
valueToStringConverter,
|
||||
componentsTourSteps,
|
||||
}),
|
||||
[
|
||||
componentsTourSteps,
|
||||
darkMode,
|
||||
dataView,
|
||||
displayedRows,
|
||||
expandedDoc,
|
||||
isFilterActive,
|
||||
onFilter,
|
||||
setExpandedDoc,
|
||||
usedSelectedDocs,
|
||||
valueToStringConverter,
|
||||
]
|
||||
);
|
||||
|
||||
/**
|
||||
* Pagination
|
||||
*/
|
||||
const defaultRowsPerPage = useMemo(
|
||||
() => getDefaultRowsPerPage(services.uiSettings),
|
||||
[services.uiSettings]
|
||||
);
|
||||
const currentPageSize =
|
||||
typeof rowsPerPageState === 'number' && rowsPerPageState > 0
|
||||
? rowsPerPageState
|
||||
: defaultRowsPerPage;
|
||||
: DEFAULT_ROWS_PER_PAGE;
|
||||
const [pagination, setPagination] = useState({
|
||||
pageIndex: 0,
|
||||
pageSize: currentPageSize,
|
||||
|
@ -371,10 +449,17 @@ export const DiscoverGrid = ({
|
|||
onChangePage,
|
||||
pageIndex: pagination.pageIndex > pageCount - 1 ? 0 : pagination.pageIndex,
|
||||
pageSize: pagination.pageSize,
|
||||
pageSizeOptions: getRowsPerPageOptions(pagination.pageSize),
|
||||
pageSizeOptions: rowsPerPageOptions ?? getRowsPerPageOptions(pagination.pageSize),
|
||||
}
|
||||
: undefined;
|
||||
}, [pagination, pageCount, isPaginationEnabled, onUpdateRowsPerPage]);
|
||||
}, [
|
||||
isPaginationEnabled,
|
||||
pagination.pageIndex,
|
||||
pagination.pageSize,
|
||||
pageCount,
|
||||
rowsPerPageOptions,
|
||||
onUpdateRowsPerPage,
|
||||
]);
|
||||
|
||||
useEffect(() => {
|
||||
setPagination((paginationData) =>
|
||||
|
@ -403,8 +488,6 @@ export const DiscoverGrid = ({
|
|||
[onSort, isSortEnabled, isPlainRecord, setInmemorySortingColumns]
|
||||
);
|
||||
|
||||
const showMultiFields = services.uiSettings.get(SHOW_MULTIFIELDS);
|
||||
|
||||
const shouldShowFieldHandler = useMemo(() => {
|
||||
const dataViewFields = dataView.fields.getAll().map((fld) => fld.name);
|
||||
return getShouldShowFieldHandler(dataViewFields, dataView, showMultiFields);
|
||||
|
@ -420,10 +503,20 @@ export const DiscoverGrid = ({
|
|||
displayedRows,
|
||||
useNewFieldsApi,
|
||||
shouldShowFieldHandler,
|
||||
services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED),
|
||||
() => dataGridRef.current?.closeCellPopover()
|
||||
() => dataGridRef.current?.closeCellPopover(),
|
||||
services.fieldFormats,
|
||||
maxDocFieldsDisplayed,
|
||||
externalCustomRenderers
|
||||
),
|
||||
[dataView, displayedRows, useNewFieldsApi, shouldShowFieldHandler, services.uiSettings]
|
||||
[
|
||||
dataView,
|
||||
displayedRows,
|
||||
useNewFieldsApi,
|
||||
shouldShowFieldHandler,
|
||||
maxDocFieldsDisplayed,
|
||||
services.fieldFormats,
|
||||
externalCustomRenderers,
|
||||
]
|
||||
);
|
||||
|
||||
/**
|
||||
|
@ -459,7 +552,7 @@ export const DiscoverGrid = ({
|
|||
);
|
||||
|
||||
const visibleColumns = useMemo(
|
||||
() => getVisibleColumns(displayedColumns, dataView, showTimeCol) as string[],
|
||||
() => getVisibleColumns(displayedColumns, dataView, showTimeCol),
|
||||
[dataView, displayedColumns, showTimeCol]
|
||||
);
|
||||
|
||||
|
@ -511,6 +604,7 @@ export const DiscoverGrid = ({
|
|||
valueToStringConverter,
|
||||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
}),
|
||||
[
|
||||
onFilter,
|
||||
|
@ -527,6 +621,7 @@ export const DiscoverGrid = ({
|
|||
dataViewFieldEditor,
|
||||
valueToStringConverter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -554,26 +649,33 @@ export const DiscoverGrid = ({
|
|||
return { columns: sortingColumns, onSort: () => {} };
|
||||
}, [isSortEnabled, sortingColumns, isPlainRecord, inmemorySortingColumns, onTableSort]);
|
||||
|
||||
const canSetExpandedDoc = Boolean(setExpandedDoc && DocumentView);
|
||||
const canSetExpandedDoc = Boolean(setExpandedDoc && !!renderDocumentView);
|
||||
|
||||
const lead = useMemo(
|
||||
() =>
|
||||
getLeadControlColumns(canSetExpandedDoc).filter(({ id }) => controlColumnIds.includes(id)),
|
||||
[controlColumnIds, canSetExpandedDoc]
|
||||
);
|
||||
const leadingControlColumns = useMemo(() => {
|
||||
const internalControlColumns = getLeadControlColumns(canSetExpandedDoc).filter(({ id }) =>
|
||||
controlColumnIds.includes(id)
|
||||
);
|
||||
return externalControlColumns
|
||||
? [...internalControlColumns, ...externalControlColumns]
|
||||
: internalControlColumns;
|
||||
}, [canSetExpandedDoc, externalControlColumns, controlColumnIds]);
|
||||
|
||||
const additionalControls = useMemo(
|
||||
() =>
|
||||
usedSelectedDocs.length ? (
|
||||
<DiscoverGridDocumentToolbarBtn
|
||||
isFilterActive={isFilterActive}
|
||||
rows={rows!}
|
||||
selectedDocs={usedSelectedDocs}
|
||||
setSelectedDocs={setSelectedDocs}
|
||||
setIsFilterActive={setIsFilterActive}
|
||||
/>
|
||||
) : null,
|
||||
[usedSelectedDocs, isFilterActive, rows, setIsFilterActive]
|
||||
() => (
|
||||
<>
|
||||
{usedSelectedDocs.length ? (
|
||||
<DataTableDocumentToolbarBtn
|
||||
isFilterActive={isFilterActive}
|
||||
rows={rows!}
|
||||
selectedDocs={usedSelectedDocs}
|
||||
setSelectedDocs={setSelectedDocs}
|
||||
setIsFilterActive={setIsFilterActive}
|
||||
/>
|
||||
) : null}
|
||||
{externalAdditionalControls}
|
||||
</>
|
||||
),
|
||||
[usedSelectedDocs, isFilterActive, rows, externalAdditionalControls]
|
||||
);
|
||||
|
||||
const showDisplaySelector = useMemo(
|
||||
|
@ -617,17 +719,20 @@ export const DiscoverGrid = ({
|
|||
const rowHeightsOptions = useRowHeightsOptions({
|
||||
rowHeightState,
|
||||
onUpdateRowHeight,
|
||||
storage,
|
||||
configRowHeight,
|
||||
consumer,
|
||||
});
|
||||
|
||||
const isRenderComplete = loadingState !== DataLoadingState.loading;
|
||||
|
||||
if (!rowCount && loadingState === DataLoadingState.loading) {
|
||||
return (
|
||||
<div className="euiDataGrid__loading" data-test-subj="discoverDataGridLoading">
|
||||
<div className="euiDataGrid__loading" data-test-subj="unifiedDataTableLoading">
|
||||
<EuiText size="xs" color="subdued">
|
||||
<EuiLoadingSpinner />
|
||||
<EuiSpacer size="s" />
|
||||
<FormattedMessage id="discover.loadingResults" defaultMessage="Loading results" />
|
||||
<FormattedMessage id="unifiedDataTable.loadingResults" defaultMessage="Loading results" />
|
||||
</EuiText>
|
||||
</div>
|
||||
);
|
||||
|
@ -646,32 +751,18 @@ export const DiscoverGrid = ({
|
|||
<EuiText size="xs" color="subdued">
|
||||
<EuiIcon type="discoverApp" size="m" color="subdued" />
|
||||
<EuiSpacer size="s" />
|
||||
<FormattedMessage id="discover.noResultsFound" defaultMessage="No results found" />
|
||||
<FormattedMessage
|
||||
id="unifiedDataTable.noResultsFound"
|
||||
defaultMessage="No results found"
|
||||
/>
|
||||
</EuiText>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<DiscoverGridContext.Provider
|
||||
value={{
|
||||
expanded: expandedDoc,
|
||||
setExpanded: setExpandedDoc,
|
||||
rows: displayedRows,
|
||||
onFilter,
|
||||
dataView,
|
||||
isDarkMode: darkMode,
|
||||
selectedDocs: usedSelectedDocs,
|
||||
setSelectedDocs: (newSelectedDocs) => {
|
||||
setSelectedDocs(newSelectedDocs);
|
||||
if (isFilterActive && newSelectedDocs.length === 0) {
|
||||
setIsFilterActive(false);
|
||||
}
|
||||
},
|
||||
valueToStringConverter,
|
||||
}}
|
||||
>
|
||||
<span className="dscDiscoverGrid__inner">
|
||||
<UnifiedDataTableContext.Provider value={unifiedDataTableContextValue}>
|
||||
<span className="unifiedDataTable__inner">
|
||||
<div
|
||||
data-test-subj="discoverDocTable"
|
||||
data-render-complete={isRenderComplete}
|
||||
|
@ -679,7 +770,7 @@ export const DiscoverGrid = ({
|
|||
data-title={searchTitle}
|
||||
data-description={searchDescription}
|
||||
data-document-number={displayedRows.length}
|
||||
className={classnames(className, 'dscDiscoverGrid__table')}
|
||||
className={classnames(className, 'unifiedDataTable__table')}
|
||||
>
|
||||
<EuiDataGridMemoized
|
||||
aria-describedby={randomId}
|
||||
|
@ -687,7 +778,7 @@ export const DiscoverGrid = ({
|
|||
columns={euiGridColumns}
|
||||
columnVisibility={columnsVisibility}
|
||||
data-test-subj="docTable"
|
||||
leadingControlColumns={lead}
|
||||
leadingControlColumns={leadingControlColumns}
|
||||
onColumnResize={onResize}
|
||||
pagination={paginationObj}
|
||||
renderCellValue={renderCellValue}
|
||||
|
@ -699,11 +790,13 @@ export const DiscoverGrid = ({
|
|||
rowHeightsOptions={rowHeightsOptions}
|
||||
inMemory={inMemory}
|
||||
gridStyle={GRID_STYLE}
|
||||
renderCustomGridBody={renderCustomGridBody}
|
||||
trailingControlColumns={trailingControlColumns}
|
||||
/>
|
||||
</div>
|
||||
{loadingState !== DataLoadingState.loading &&
|
||||
isPaginationEnabled && ( // we hide the footer for Surrounding Documents page
|
||||
<DiscoverGridFooter
|
||||
<UnifiedDataTableFooter
|
||||
isLoadingMore={loadingState === DataLoadingState.loadingMore}
|
||||
rowCount={rowCount}
|
||||
sampleSize={sampleSize}
|
||||
|
@ -711,6 +804,8 @@ export const DiscoverGrid = ({
|
|||
pageIndex={paginationObj?.pageIndex}
|
||||
totalHits={totalHits}
|
||||
onFetchMoreRecords={onFetchMoreRecords}
|
||||
data={data}
|
||||
fieldFormats={fieldFormats}
|
||||
/>
|
||||
)}
|
||||
{searchTitle && (
|
||||
|
@ -718,13 +813,13 @@ export const DiscoverGrid = ({
|
|||
<p id={String(randomId)}>
|
||||
{searchDescription ? (
|
||||
<FormattedMessage
|
||||
id="discover.searchGenerationWithDescriptionGrid"
|
||||
id="unifiedDataTable.searchGenerationWithDescriptionGrid"
|
||||
defaultMessage="Table generated by search {searchTitle} ({searchDescription})"
|
||||
values={{ searchTitle, searchDescription }}
|
||||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="discover.searchGenerationWithDescription"
|
||||
id="unifiedDataTable.searchGenerationWithDescription"
|
||||
defaultMessage="Table generated by search {searchTitle}"
|
||||
values={{ searchTitle }}
|
||||
/>
|
||||
|
@ -732,24 +827,10 @@ export const DiscoverGrid = ({
|
|||
</p>
|
||||
</EuiScreenReaderOnly>
|
||||
)}
|
||||
{setExpandedDoc && expandedDoc && DocumentView && (
|
||||
<DocumentView
|
||||
dataView={dataView}
|
||||
hit={expandedDoc}
|
||||
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={defaultColumns ? [] : displayedColumns}
|
||||
filters={filters}
|
||||
savedSearchId={savedSearchId}
|
||||
onFilter={onFilter}
|
||||
onRemoveColumn={onRemoveColumn}
|
||||
onAddColumn={onAddColumn}
|
||||
onClose={() => setExpandedDoc(undefined)}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
query={query}
|
||||
/>
|
||||
)}
|
||||
{canSetExpandedDoc &&
|
||||
expandedDoc &&
|
||||
renderDocumentView!(expandedDoc, displayedRows, displayedColumns)}
|
||||
</span>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
};
|
|
@ -7,10 +7,10 @@
|
|||
*/
|
||||
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { getEuiGridColumns, getVisibleColumns } from './discover_grid_columns';
|
||||
import { getEuiGridColumns, getVisibleColumns } from './data_table_columns';
|
||||
import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield';
|
||||
import { discoverGridContextMock } from '../../__mocks__/grid_context';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
import { dataTableContextMock } from '../../__mocks__/table_context';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
|
||||
const columns = ['extension', 'message'];
|
||||
const columnsWithTimeCol = getVisibleColumns(
|
||||
|
@ -19,7 +19,7 @@ const columnsWithTimeCol = getVisibleColumns(
|
|||
true
|
||||
) as string[];
|
||||
|
||||
describe('Discover grid columns', function () {
|
||||
describe('Data table columns', function () {
|
||||
describe('getEuiGridColumns', () => {
|
||||
it('returns eui grid columns showing default columns', async () => {
|
||||
const actual = getEuiGridColumns({
|
||||
|
@ -29,14 +29,14 @@ describe('Discover grid columns', function () {
|
|||
defaultColumns: true,
|
||||
isSortEnabled: true,
|
||||
isPlainRecord: false,
|
||||
valueToStringConverter: discoverGridContextMock.valueToStringConverter,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 100,
|
||||
services: {
|
||||
uiSettings: discoverServiceMock.uiSettings,
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
uiSettings: servicesMock.uiSettings,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
},
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
|
@ -52,7 +52,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -66,7 +66,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -86,6 +86,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "extension",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
|
@ -98,7 +99,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -112,7 +113,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -130,6 +131,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "message",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -143,14 +145,14 @@ describe('Discover grid columns', function () {
|
|||
defaultColumns: false,
|
||||
isSortEnabled: true,
|
||||
isPlainRecord: false,
|
||||
valueToStringConverter: discoverGridContextMock.valueToStringConverter,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 100,
|
||||
services: {
|
||||
uiSettings: discoverServiceMock.uiSettings,
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
uiSettings: servicesMock.uiSettings,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
},
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
|
@ -166,7 +168,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -180,7 +182,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -219,6 +221,7 @@ describe('Discover grid columns', function () {
|
|||
"initialWidth": 210,
|
||||
"isSortable": true,
|
||||
"schema": "datetime",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
|
@ -231,7 +234,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -245,7 +248,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -268,6 +271,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "extension",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
|
@ -280,7 +284,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -294,7 +298,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -315,6 +319,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "message",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
|
@ -328,14 +333,14 @@ describe('Discover grid columns', function () {
|
|||
defaultColumns: false,
|
||||
isSortEnabled: true,
|
||||
isPlainRecord: true,
|
||||
valueToStringConverter: discoverGridContextMock.valueToStringConverter,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 100,
|
||||
services: {
|
||||
uiSettings: discoverServiceMock.uiSettings,
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
uiSettings: servicesMock.uiSettings,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
},
|
||||
hasEditDataViewPermission: () =>
|
||||
discoverServiceMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
|
@ -351,7 +356,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -365,7 +370,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -404,6 +409,7 @@ describe('Discover grid columns', function () {
|
|||
"initialWidth": 210,
|
||||
"isSortable": true,
|
||||
"schema": "datetime",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
|
@ -416,7 +422,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -430,7 +436,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -453,6 +459,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "extension",
|
||||
"isSortable": true,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
|
@ -465,7 +472,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="discover.grid.copyColumnNameToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -479,7 +486,7 @@ describe('Discover grid columns', function () {
|
|||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="discover.grid.copyColumnValuesToClipBoardButton"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
|
@ -500,6 +507,7 @@ describe('Discover grid columns', function () {
|
|||
"id": "message",
|
||||
"isSortable": true,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
|
@ -17,14 +17,14 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { ToastsStart, IUiSettingsClient } from '@kbn/core/public';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { ExpandButton } from './discover_grid_expand_button';
|
||||
import { DiscoverGridSettings } from './types';
|
||||
import type { ValueToStringConverter } from '../../types';
|
||||
import { buildCellActions } from './discover_grid_cell_actions';
|
||||
import { getSchemaByKbnType } from './discover_grid_schema';
|
||||
import { SelectButton } from './discover_grid_document_selection';
|
||||
import { defaultTimeColumnWidth } from './constants';
|
||||
import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { ExpandButton } from './data_table_expand_button';
|
||||
import { UnifiedDataTableSettings } from '../types';
|
||||
import type { ValueToStringConverter } from '../types';
|
||||
import { buildCellActions } from './default_cell_actions';
|
||||
import { getSchemaByKbnType } from './data_table_schema';
|
||||
import { SelectButton } from './data_table_document_selection';
|
||||
import { defaultTimeColumnWidth } from '../constants';
|
||||
import { buildCopyColumnNameButton, buildCopyColumnValuesButton } from './build_copy_column_button';
|
||||
import { buildEditFieldButton } from './build_edit_field_button';
|
||||
|
||||
|
@ -34,7 +34,7 @@ const openDetails = {
|
|||
headerCellRender: () => (
|
||||
<EuiScreenReaderOnly>
|
||||
<span>
|
||||
{i18n.translate('discover.controlColumnHeader', {
|
||||
{i18n.translate('unifiedDataTable.controlColumnHeader', {
|
||||
defaultMessage: 'Control column',
|
||||
})}
|
||||
</span>
|
||||
|
@ -50,7 +50,7 @@ const select = {
|
|||
headerCellRender: () => (
|
||||
<EuiScreenReaderOnly>
|
||||
<span>
|
||||
{i18n.translate('discover.selectColumnHeader', {
|
||||
{i18n.translate('unifiedDataTable.selectColumnHeader', {
|
||||
defaultMessage: 'Select column',
|
||||
})}
|
||||
</span>
|
||||
|
@ -79,6 +79,7 @@ function buildEuiGridColumn({
|
|||
onFilter,
|
||||
editField,
|
||||
columnCellActions,
|
||||
visibleCellActions,
|
||||
}: {
|
||||
columnName: string;
|
||||
columnWidth: number | undefined;
|
||||
|
@ -93,6 +94,7 @@ function buildEuiGridColumn({
|
|||
onFilter?: DocViewFilterFn;
|
||||
editField?: (fieldName: string) => void;
|
||||
columnCellActions?: EuiDataGridColumnCellAction[];
|
||||
visibleCellActions?: number;
|
||||
}) {
|
||||
const dataViewField = dataView.getFieldByName(columnName);
|
||||
const editFieldButton =
|
||||
|
@ -101,16 +103,19 @@ function buildEuiGridColumn({
|
|||
buildEditFieldButton({ hasEditDataViewPermission, dataView, field: dataViewField, editField });
|
||||
const columnDisplayName =
|
||||
columnName === '_source'
|
||||
? i18n.translate('discover.grid.documentHeader', {
|
||||
? i18n.translate('unifiedDataTable.grid.documentHeader', {
|
||||
defaultMessage: 'Document',
|
||||
})
|
||||
: dataViewField?.displayName || columnName;
|
||||
|
||||
let cellActions: EuiDataGridColumnCellAction[];
|
||||
|
||||
if (columnCellActions?.length) {
|
||||
cellActions = columnCellActions;
|
||||
} else {
|
||||
cellActions = dataViewField ? buildCellActions(dataViewField, onFilter) : [];
|
||||
cellActions = dataViewField
|
||||
? buildCellActions(dataViewField, toastNotifications, valueToStringConverter, onFilter)
|
||||
: [];
|
||||
}
|
||||
|
||||
const column: EuiDataGridColumn = {
|
||||
|
@ -123,7 +128,7 @@ function buildEuiGridColumn({
|
|||
defaultColumns || columnName === dataView.timeFieldName
|
||||
? false
|
||||
: {
|
||||
label: i18n.translate('discover.removeColumnLabel', {
|
||||
label: i18n.translate('unifiedDataTable.removeColumnLabel', {
|
||||
defaultMessage: 'Remove column',
|
||||
}),
|
||||
iconType: 'cross',
|
||||
|
@ -150,23 +155,21 @@ function buildEuiGridColumn({
|
|||
],
|
||||
},
|
||||
cellActions,
|
||||
visibleCellActions,
|
||||
};
|
||||
|
||||
if (column.id === dataView.timeFieldName) {
|
||||
const timeFieldName = dataViewField?.customLabel ?? dataView.timeFieldName;
|
||||
const primaryTimeAriaLabel = i18n.translate(
|
||||
'discover.docTable.tableHeader.timeFieldIconTooltipAriaLabel',
|
||||
'unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel',
|
||||
{
|
||||
defaultMessage: '{timeFieldName} - this field represents the time that events occurred.',
|
||||
values: { timeFieldName },
|
||||
}
|
||||
);
|
||||
const primaryTimeTooltip = i18n.translate(
|
||||
'discover.docTable.tableHeader.timeFieldIconTooltip',
|
||||
{
|
||||
defaultMessage: 'This field represents the time that events occurred.',
|
||||
}
|
||||
);
|
||||
const primaryTimeTooltip = i18n.translate('unifiedDataTable.tableHeader.timeFieldIconTooltip', {
|
||||
defaultMessage: 'This field represents the time that events occurred.',
|
||||
});
|
||||
|
||||
column.display = (
|
||||
<div aria-label={primaryTimeAriaLabel}>
|
||||
|
@ -199,11 +202,12 @@ export function getEuiGridColumns({
|
|||
valueToStringConverter,
|
||||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
}: {
|
||||
columns: string[];
|
||||
columnsCellActions?: EuiDataGridColumnCellAction[][];
|
||||
rowsCount: number;
|
||||
settings: DiscoverGridSettings | undefined;
|
||||
settings: UnifiedDataTableSettings | undefined;
|
||||
dataView: DataView;
|
||||
defaultColumns: boolean;
|
||||
isSortEnabled: boolean;
|
||||
|
@ -216,6 +220,7 @@ export function getEuiGridColumns({
|
|||
valueToStringConverter: ValueToStringConverter;
|
||||
onFilter: DocViewFilterFn;
|
||||
editField?: (fieldName: string) => void;
|
||||
visibleCellActions?: number;
|
||||
}) {
|
||||
const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0;
|
||||
|
||||
|
@ -234,6 +239,7 @@ export function getEuiGridColumns({
|
|||
rowsCount,
|
||||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
})
|
||||
);
|
||||
}
|
|
@ -8,9 +8,9 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { DiscoverGridDocumentToolbarBtn, SelectButton } from './discover_grid_document_selection';
|
||||
import { discoverGridContextMock } from '../../__mocks__/grid_context';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { DataTableDocumentToolbarBtn, SelectButton } from './data_table_document_selection';
|
||||
import { dataTableContextMock } from '../../__mocks__/table_context';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
import { getDocId } from '@kbn/discover-utils';
|
||||
|
||||
describe('document selection', () => {
|
||||
|
@ -35,11 +35,11 @@ describe('document selection', () => {
|
|||
describe('SelectButton', () => {
|
||||
test('is not checked', () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
...dataTableContextMock,
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<SelectButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -49,7 +49,7 @@ describe('document selection', () => {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
|
||||
const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
|
||||
|
@ -58,12 +58,12 @@ describe('document selection', () => {
|
|||
|
||||
test('is checked', () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
...dataTableContextMock,
|
||||
selectedDocs: ['i::1::'],
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<SelectButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -73,7 +73,7 @@ describe('document selection', () => {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
|
||||
const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
|
||||
|
@ -82,11 +82,11 @@ describe('document selection', () => {
|
|||
|
||||
test('adding a selection', () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
...dataTableContextMock,
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<SelectButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -96,7 +96,7 @@ describe('document selection', () => {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
|
||||
const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
|
||||
|
@ -105,12 +105,12 @@ describe('document selection', () => {
|
|||
});
|
||||
test('removing a selection', () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
...dataTableContextMock,
|
||||
selectedDocs: ['i::1::'],
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<SelectButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -120,7 +120,7 @@ describe('document selection', () => {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
|
||||
const checkBox = findTestSubject(component, 'dscGridSelectDoc-i::1::');
|
||||
|
@ -128,16 +128,16 @@ describe('document selection', () => {
|
|||
expect(contextMock.setSelectedDocs).toHaveBeenCalledWith([]);
|
||||
});
|
||||
});
|
||||
describe('DiscoverGridDocumentToolbarBtn', () => {
|
||||
describe('DataTableDocumentToolbarBtn', () => {
|
||||
test('it renders a button clickable button', () => {
|
||||
const props = {
|
||||
isFilterActive: false,
|
||||
rows: discoverGridContextMock.rows,
|
||||
rows: dataTableContextMock.rows,
|
||||
selectedDocs: ['i::1::'],
|
||||
setIsFilterActive: jest.fn(),
|
||||
setSelectedDocs: jest.fn(),
|
||||
};
|
||||
const component = mountWithIntl(<DiscoverGridDocumentToolbarBtn {...props} />);
|
||||
const component = mountWithIntl(<DataTableDocumentToolbarBtn {...props} />);
|
||||
const button = findTestSubject(component, 'dscGridSelectionBtn');
|
||||
expect(button.length).toBe(1);
|
||||
});
|
|
@ -20,15 +20,15 @@ import { FormattedMessage } from '@kbn/i18n-react';
|
|||
import { euiDarkVars as themeDark, euiLightVars as themeLight } from '@kbn/ui-theme';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
|
||||
export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => {
|
||||
const { selectedDocs, expanded, rows, isDarkMode, setSelectedDocs } =
|
||||
useContext(DiscoverGridContext);
|
||||
useContext(UnifiedDataTableContext);
|
||||
const doc = useMemo(() => rows[rowIndex], [rows, rowIndex]);
|
||||
const checked = useMemo(() => selectedDocs.includes(doc.id), [selectedDocs, doc.id]);
|
||||
|
||||
const toggleDocumentSelectionLabel = i18n.translate('discover.grid.selectDoc', {
|
||||
const toggleDocumentSelectionLabel = i18n.translate('unifiedDataTable.grid.selectDoc', {
|
||||
defaultMessage: `Select document '{rowNumber}'`,
|
||||
values: { rowNumber: rowIndex + 1 },
|
||||
});
|
||||
|
@ -63,7 +63,7 @@ export const SelectButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle
|
|||
);
|
||||
};
|
||||
|
||||
export function DiscoverGridDocumentToolbarBtn({
|
||||
export function DataTableDocumentToolbarBtn({
|
||||
isFilterActive,
|
||||
rows,
|
||||
selectedDocs,
|
||||
|
@ -90,7 +90,10 @@ export function DiscoverGridDocumentToolbarBtn({
|
|||
setIsFilterActive(false);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="discover.showAllDocuments" defaultMessage="Show all documents" />
|
||||
<FormattedMessage
|
||||
id="unifiedDataTable.showAllDocuments"
|
||||
defaultMessage="Show all documents"
|
||||
/>
|
||||
</EuiContextMenuItem>
|
||||
) : (
|
||||
<EuiContextMenuItem
|
||||
|
@ -103,7 +106,7 @@ export function DiscoverGridDocumentToolbarBtn({
|
|||
}}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="discover.showSelectedDocumentsOnly"
|
||||
id="unifiedDataTable.showSelectedDocumentsOnly"
|
||||
defaultMessage="Show selected documents only"
|
||||
/>
|
||||
</EuiContextMenuItem>
|
||||
|
@ -122,7 +125,7 @@ export function DiscoverGridDocumentToolbarBtn({
|
|||
{(copy) => (
|
||||
<EuiContextMenuItem key="copyJSON" icon="copyClipboard" onClick={copy}>
|
||||
<FormattedMessage
|
||||
id="discover.copyToClipboardJSON"
|
||||
id="unifiedDataTable.copyToClipboardJSON"
|
||||
defaultMessage="Copy documents to clipboard (JSON)"
|
||||
/>
|
||||
</EuiContextMenuItem>
|
||||
|
@ -138,7 +141,7 @@ export function DiscoverGridDocumentToolbarBtn({
|
|||
setIsFilterActive(false);
|
||||
}}
|
||||
>
|
||||
<FormattedMessage id="discover.clearSelection" defaultMessage="Clear selection" />
|
||||
<FormattedMessage id="unifiedDataTable.clearSelection" defaultMessage="Clear selection" />
|
||||
</EuiContextMenuItem>,
|
||||
];
|
||||
}, [
|
||||
|
@ -176,7 +179,7 @@ export function DiscoverGridDocumentToolbarBtn({
|
|||
})}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="discover.selectedDocumentsNumber"
|
||||
id="unifiedDataTable.selectedDocumentsNumber"
|
||||
defaultMessage="{nr} documents selected"
|
||||
values={{ nr: selectedDocs.length }}
|
||||
/>
|
|
@ -9,18 +9,18 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { ExpandButton } from './discover_grid_expand_button';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { discoverGridContextMock } from '../../__mocks__/grid_context';
|
||||
import { ExpandButton } from './data_table_expand_button';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
import { dataTableContextMock } from '../../__mocks__/table_context';
|
||||
|
||||
describe('Discover grid view button ', function () {
|
||||
describe('Data table view button ', function () {
|
||||
it('when no document is expanded, setExpanded is called with current document', async () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
...dataTableContextMock,
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<ExpandButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -30,20 +30,20 @@ describe('Discover grid view button ', function () {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'docTableExpandToggleColumn');
|
||||
await button.simulate('click');
|
||||
expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[0]);
|
||||
expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[0]);
|
||||
});
|
||||
it('when the current document is expanded, setExpanded is called with undefined', async () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
expanded: discoverGridContextMock.rows[0],
|
||||
...dataTableContextMock,
|
||||
expanded: dataTableContextMock.rows[0],
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<ExpandButton
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
|
@ -53,7 +53,7 @@ describe('Discover grid view button ', function () {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'docTableExpandToggleColumn');
|
||||
await button.simulate('click');
|
||||
|
@ -61,12 +61,12 @@ describe('Discover grid view button ', function () {
|
|||
});
|
||||
it('when another document is expanded, setExpanded is called with the current document', async () => {
|
||||
const contextMock = {
|
||||
...discoverGridContextMock,
|
||||
expanded: discoverGridContextMock.rows[0],
|
||||
...dataTableContextMock,
|
||||
expanded: dataTableContextMock.rows[0],
|
||||
};
|
||||
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={contextMock}>
|
||||
<UnifiedDataTableContext.Provider value={contextMock}>
|
||||
<ExpandButton
|
||||
rowIndex={1}
|
||||
colIndex={0}
|
||||
|
@ -76,10 +76,10 @@ describe('Discover grid view button ', function () {
|
|||
isDetails={false}
|
||||
isExpandable={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'docTableExpandToggleColumn');
|
||||
await button.simulate('click');
|
||||
expect(contextMock.setExpanded).toHaveBeenCalledWith(discoverGridContextMock.rows[1]);
|
||||
expect(contextMock.setExpanded).toHaveBeenCalledWith(dataTableContextMock.rows[1]);
|
||||
});
|
||||
});
|
|
@ -10,8 +10,7 @@ import React, { useContext, useEffect, useRef, useState } from 'react';
|
|||
import { EuiButtonIcon, EuiDataGridCellValueElementProps, EuiToolTip } from '@elastic/eui';
|
||||
import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../discover_tour';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
|
||||
/**
|
||||
* Button to expand a given row
|
||||
|
@ -19,9 +18,11 @@ import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../discover_tour';
|
|||
export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueElementProps) => {
|
||||
const toolTipRef = useRef<EuiToolTip>(null);
|
||||
const [pressed, setPressed] = useState<boolean>(false);
|
||||
const { expanded, setExpanded, rows, isDarkMode } = useContext(DiscoverGridContext);
|
||||
const { expanded, setExpanded, rows, isDarkMode, componentsTourSteps } =
|
||||
useContext(UnifiedDataTableContext);
|
||||
const current = rows[rowIndex];
|
||||
|
||||
const tourStep = componentsTourSteps ? componentsTourSteps.expandButton : undefined;
|
||||
useEffect(() => {
|
||||
if (current.isAnchor) {
|
||||
setCellProps({
|
||||
|
@ -39,7 +40,7 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle
|
|||
}, [expanded, current, setCellProps, isDarkMode]);
|
||||
|
||||
const isCurrentRowExpanded = current === expanded;
|
||||
const buttonLabel = i18n.translate('discover.grid.viewDoc', {
|
||||
const buttonLabel = i18n.translate('unifiedDataTable.grid.viewDoc', {
|
||||
defaultMessage: 'Toggle dialog with details',
|
||||
});
|
||||
|
||||
|
@ -63,7 +64,7 @@ export const ExpandButton = ({ rowIndex, setCellProps }: EuiDataGridCellValueEle
|
|||
return (
|
||||
<EuiToolTip content={buttonLabel} delay="long" ref={toolTipRef}>
|
||||
<EuiButtonIcon
|
||||
id={rowIndex === 0 ? DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument : undefined}
|
||||
id={rowIndex === 0 ? tourStep : undefined}
|
||||
size="xs"
|
||||
iconSize="s"
|
||||
aria-label={buttonLabel}
|
|
@ -9,20 +9,22 @@
|
|||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { UnifiedDataTableFooter } from './data_table_footer';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { DiscoverGridFooter } from './discover_grid_footer';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
|
||||
describe('DiscoverGridFooter', function () {
|
||||
describe('UnifiedDataTableFooter', function () {
|
||||
it('should not render anything when not on the last page', async () => {
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
<KibanaContextProvider services={servicesMock}>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={5}
|
||||
pageIndex={0}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
);
|
||||
|
@ -31,32 +33,32 @@ describe('DiscoverGridFooter', function () {
|
|||
|
||||
it('should not render anything yet when all rows shown', async () => {
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={500}
|
||||
rowCount={500}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={500}
|
||||
rowCount={500}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
);
|
||||
expect(component.isEmptyRender()).toBe(true);
|
||||
});
|
||||
|
||||
it('should render a message for the last page', async () => {
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
);
|
||||
expect(findTestSubject(component, 'discoverTableFooter').text()).toBe(
|
||||
expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe(
|
||||
'Search results are limited to 500 documents. Add more search terms to narrow your search.'
|
||||
);
|
||||
expect(findTestSubject(component, 'dscGridSampleSizeFetchMoreLink').exists()).toBe(false);
|
||||
|
@ -66,19 +68,19 @@ describe('DiscoverGridFooter', function () {
|
|||
const mockLoadMore = jest.fn();
|
||||
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
isLoadingMore={false}
|
||||
onFetchMoreRecords={mockLoadMore}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
isLoadingMore={false}
|
||||
onFetchMoreRecords={mockLoadMore}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
);
|
||||
expect(findTestSubject(component, 'discoverTableFooter').text()).toBe(
|
||||
expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe(
|
||||
'Search results are limited to 500 documents.Load more'
|
||||
);
|
||||
|
||||
|
@ -94,19 +96,19 @@ describe('DiscoverGridFooter', function () {
|
|||
const mockLoadMore = jest.fn();
|
||||
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
isLoadingMore={true}
|
||||
onFetchMoreRecords={mockLoadMore}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={5}
|
||||
pageIndex={4}
|
||||
sampleSize={500}
|
||||
totalHits={1000}
|
||||
rowCount={500}
|
||||
isLoadingMore={true}
|
||||
onFetchMoreRecords={mockLoadMore}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
);
|
||||
expect(findTestSubject(component, 'discoverTableFooter').text()).toBe(
|
||||
expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe(
|
||||
'Search results are limited to 500 documents.Load more'
|
||||
);
|
||||
|
||||
|
@ -121,17 +123,17 @@ describe('DiscoverGridFooter', function () {
|
|||
|
||||
it('should render a message when max total limit is reached', async () => {
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={discoverServiceMock}>
|
||||
<DiscoverGridFooter
|
||||
pageCount={100}
|
||||
pageIndex={99}
|
||||
sampleSize={500}
|
||||
totalHits={11000}
|
||||
rowCount={10000}
|
||||
/>
|
||||
</KibanaContextProvider>
|
||||
<UnifiedDataTableFooter
|
||||
pageCount={100}
|
||||
pageIndex={99}
|
||||
sampleSize={500}
|
||||
totalHits={11000}
|
||||
rowCount={10000}
|
||||
data={servicesMock.data}
|
||||
fieldFormats={servicesMock.fieldFormats}
|
||||
/>
|
||||
);
|
||||
expect(findTestSubject(component, 'discoverTableFooter').text()).toBe(
|
||||
expect(findTestSubject(component, 'unifiedDataTableFooter').text()).toBe(
|
||||
'Search results are limited to 10000 documents. Add more search terms to narrow your search.'
|
||||
);
|
||||
});
|
|
@ -12,10 +12,11 @@ import { EuiButtonEmpty, EuiToolTip, useEuiTheme } from '@elastic/eui';
|
|||
import { css } from '@emotion/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ES_FIELD_TYPES, KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||
import { MAX_LOADED_GRID_ROWS } from '../../../common/constants';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { MAX_LOADED_GRID_ROWS } from '../constants';
|
||||
|
||||
export interface DiscoverGridFooterProps {
|
||||
export interface UnifiedDataTableFooterProps {
|
||||
isLoadingMore?: boolean;
|
||||
rowCount: number;
|
||||
sampleSize: number;
|
||||
|
@ -23,9 +24,11 @@ export interface DiscoverGridFooterProps {
|
|||
pageCount: number;
|
||||
totalHits?: number;
|
||||
onFetchMoreRecords?: () => void;
|
||||
data: DataPublicPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
}
|
||||
|
||||
export const DiscoverGridFooter: React.FC<DiscoverGridFooterProps> = (props) => {
|
||||
export const UnifiedDataTableFooter: React.FC<UnifiedDataTableFooterProps> = (props) => {
|
||||
const {
|
||||
isLoadingMore,
|
||||
rowCount,
|
||||
|
@ -34,8 +37,8 @@ export const DiscoverGridFooter: React.FC<DiscoverGridFooterProps> = (props) =>
|
|||
pageCount,
|
||||
totalHits = 0,
|
||||
onFetchMoreRecords,
|
||||
data,
|
||||
} = props;
|
||||
const { data } = useDiscoverServices();
|
||||
const timefilter = data.query.timefilter.timefilter;
|
||||
const [refreshInterval, setRefreshInterval] = useState(timefilter.getRefreshInterval());
|
||||
|
||||
|
@ -58,15 +61,15 @@ export const DiscoverGridFooter: React.FC<DiscoverGridFooterProps> = (props) =>
|
|||
return null;
|
||||
}
|
||||
|
||||
// allow to fetch more records on Discover page
|
||||
// allow to fetch more records for UnifiedDataTable
|
||||
if (onFetchMoreRecords && typeof isLoadingMore === 'boolean') {
|
||||
if (rowCount <= MAX_LOADED_GRID_ROWS - sampleSize) {
|
||||
return (
|
||||
<DiscoverGridFooterContainer hasButton={true} {...props}>
|
||||
<UnifiedDataTableFooterContainer hasButton={true} {...props}>
|
||||
<EuiToolTip
|
||||
content={
|
||||
isRefreshIntervalOn
|
||||
? i18n.translate('discover.gridSampleSize.fetchMoreLinkDisabledTooltip', {
|
||||
? i18n.translate('unifiedDataTable.gridSampleSize.fetchMoreLinkDisabledTooltip', {
|
||||
defaultMessage: 'To load more the refresh interval needs to be disabled first',
|
||||
})
|
||||
: undefined
|
||||
|
@ -83,37 +86,37 @@ export const DiscoverGridFooter: React.FC<DiscoverGridFooterProps> = (props) =>
|
|||
`}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="discover.gridSampleSize.fetchMoreLinkLabel"
|
||||
id="unifiedDataTable.gridSampleSize.fetchMoreLinkLabel"
|
||||
defaultMessage="Load more"
|
||||
/>
|
||||
</EuiButtonEmpty>
|
||||
</EuiToolTip>
|
||||
</DiscoverGridFooterContainer>
|
||||
</UnifiedDataTableFooterContainer>
|
||||
);
|
||||
}
|
||||
|
||||
return <DiscoverGridFooterContainer hasButton={false} {...props} />;
|
||||
return <UnifiedDataTableFooterContainer hasButton={false} {...props} />;
|
||||
}
|
||||
|
||||
if (rowCount < totalHits) {
|
||||
// show only a message for embeddable
|
||||
return <DiscoverGridFooterContainer hasButton={false} {...props} />;
|
||||
return <UnifiedDataTableFooterContainer hasButton={false} {...props} />;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
interface DiscoverGridFooterContainerProps extends DiscoverGridFooterProps {
|
||||
interface UnifiedDataTableFooterContainerProps extends UnifiedDataTableFooterProps {
|
||||
hasButton: boolean;
|
||||
}
|
||||
|
||||
const DiscoverGridFooterContainer: React.FC<DiscoverGridFooterContainerProps> = ({
|
||||
const UnifiedDataTableFooterContainer: React.FC<UnifiedDataTableFooterContainerProps> = ({
|
||||
hasButton,
|
||||
rowCount,
|
||||
children,
|
||||
fieldFormats,
|
||||
}) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const { fieldFormats } = useDiscoverServices();
|
||||
|
||||
const formattedRowCount = fieldFormats
|
||||
.getDefaultInstance(KBN_FIELD_TYPES.NUMBER, [ES_FIELD_TYPES.INTEGER])
|
||||
|
@ -121,7 +124,7 @@ const DiscoverGridFooterContainer: React.FC<DiscoverGridFooterContainerProps> =
|
|||
|
||||
return (
|
||||
<p
|
||||
data-test-subj="discoverTableFooter"
|
||||
data-test-subj="unifiedDataTableFooter"
|
||||
css={css`
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
@ -139,7 +142,7 @@ const DiscoverGridFooterContainer: React.FC<DiscoverGridFooterContainerProps> =
|
|||
<span>
|
||||
{hasButton ? (
|
||||
<FormattedMessage
|
||||
id="discover.gridSampleSize.lastPageDescription"
|
||||
id="unifiedDataTable.gridSampleSize.lastPageDescription"
|
||||
defaultMessage="Search results are limited to {rowCount} documents."
|
||||
values={{
|
||||
rowCount: formattedRowCount,
|
||||
|
@ -147,7 +150,7 @@ const DiscoverGridFooterContainer: React.FC<DiscoverGridFooterContainerProps> =
|
|||
/>
|
||||
) : (
|
||||
<FormattedMessage
|
||||
id="discover.gridSampleSize.limitDescription"
|
||||
id="unifiedDataTable.gridSampleSize.limitDescription"
|
||||
defaultMessage="Search results are limited to {sampleSize} documents. Add more search terms to narrow your search."
|
||||
values={{
|
||||
sampleSize: formattedRowCount,
|
|
@ -6,8 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { KBN_FIELD_TYPES } from '@kbn/data-plugin/public';
|
||||
import { kibanaJSON } from './constants';
|
||||
import { KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||
import { kibanaJSON } from '../constants';
|
||||
|
||||
export function getSchemaByKbnType(kbnType: string | undefined) {
|
||||
// Default DataGrid schemas: boolean, numeric, datetime, json, currency, string
|
|
@ -0,0 +1,184 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
const mockCopyToClipboard = jest.fn((value) => true);
|
||||
jest.mock('@elastic/eui', () => {
|
||||
const original = jest.requireActual('@elastic/eui');
|
||||
return {
|
||||
...original,
|
||||
copyToClipboard: (value: string) => mockCopyToClipboard(value),
|
||||
};
|
||||
});
|
||||
|
||||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import {
|
||||
FilterInBtn,
|
||||
FilterOutBtn,
|
||||
buildCellActions,
|
||||
buildCopyValueButton,
|
||||
} from './default_cell_actions';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
import { EuiButton, EuiDataGridColumnCellActionProps } from '@elastic/eui';
|
||||
import { dataTableContextMock } from '../../__mocks__/table_context';
|
||||
import { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
|
||||
describe('Default cell actions ', function () {
|
||||
const CopyBtn = buildCopyValueButton(
|
||||
{
|
||||
Component: () => <></>,
|
||||
colIndex: 0,
|
||||
columnId: 'extension',
|
||||
} as unknown as EuiDataGridColumnCellActionProps,
|
||||
servicesMock.toastNotifications,
|
||||
dataTableContextMock.valueToStringConverter
|
||||
);
|
||||
|
||||
it('should not show cell actions for unfilterable fields', async () => {
|
||||
const cellActions = buildCellActions(
|
||||
{ name: 'foo', filterable: false } as DataViewField,
|
||||
servicesMock.toastNotifications,
|
||||
dataTableContextMock.valueToStringConverter
|
||||
);
|
||||
expect(cellActions.length).toEqual(1);
|
||||
expect(
|
||||
cellActions[0]({
|
||||
Component: () => <></>,
|
||||
colIndex: 1,
|
||||
columnId: 'extension',
|
||||
} as unknown as EuiDataGridColumnCellActionProps).props['aria-label']
|
||||
).toEqual(CopyBtn.props['aria-label']);
|
||||
});
|
||||
|
||||
it('should show filter actions for filterable fields', async () => {
|
||||
const cellActions = buildCellActions(
|
||||
{ name: 'foo', filterable: true } as DataViewField,
|
||||
servicesMock.toastNotifications,
|
||||
dataTableContextMock.valueToStringConverter,
|
||||
jest.fn()
|
||||
);
|
||||
expect(cellActions).toContain(FilterInBtn);
|
||||
expect(cellActions).toContain(FilterOutBtn);
|
||||
});
|
||||
|
||||
it('should show Copy action for _source field', async () => {
|
||||
const cellActions = buildCellActions(
|
||||
{ name: '_source', type: '_source', filterable: false } as DataViewField,
|
||||
servicesMock.toastNotifications,
|
||||
dataTableContextMock.valueToStringConverter
|
||||
);
|
||||
expect(
|
||||
cellActions[0]({
|
||||
Component: () => <></>,
|
||||
colIndex: 1,
|
||||
columnId: 'extension',
|
||||
} as unknown as EuiDataGridColumnCellActionProps).props['aria-label']
|
||||
).toEqual(CopyBtn.props['aria-label']);
|
||||
});
|
||||
|
||||
it('triggers filter function when FilterInBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<UnifiedDataTableContext.Provider value={dataTableContextMock}>
|
||||
<FilterInBtn
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(dataTableContextMock.onFilter).toHaveBeenCalledWith(
|
||||
dataTableContextMock.dataView.fields.getByName('extension'),
|
||||
'jpg',
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterInBtn is clicked for a non-provided value', async () => {
|
||||
const component = mountWithIntl(
|
||||
<UnifiedDataTableContext.Provider value={dataTableContextMock}>
|
||||
<FilterInBtn
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={0}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(dataTableContextMock.onFilter).toHaveBeenCalledWith(
|
||||
dataTableContextMock.dataView.fields.getByName('extension'),
|
||||
undefined,
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterInBtn is clicked for an empty string value', async () => {
|
||||
const component = mountWithIntl(
|
||||
<UnifiedDataTableContext.Provider value={dataTableContextMock}>
|
||||
<FilterInBtn
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={4}
|
||||
colIndex={1}
|
||||
columnId="message"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(dataTableContextMock.onFilter).toHaveBeenCalledWith(
|
||||
dataTableContextMock.dataView.fields.getByName('message'),
|
||||
'',
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterOutBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<UnifiedDataTableContext.Provider value={dataTableContextMock}>
|
||||
<FilterOutBtn
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterOutButton');
|
||||
await button.simulate('click');
|
||||
expect(dataTableContextMock.onFilter).toHaveBeenCalledWith(
|
||||
dataTableContextMock.dataView.fields.getByName('extension'),
|
||||
'jpg',
|
||||
'-'
|
||||
);
|
||||
});
|
||||
it('triggers clipboard copy when CopyBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<UnifiedDataTableContext.Provider value={dataTableContextMock}>
|
||||
{buildCopyValueButton(
|
||||
{
|
||||
Component: (props: any) => <EuiButton {...props} />,
|
||||
colIndex: 1,
|
||||
rowIndex: 1,
|
||||
columnId: 'extension',
|
||||
} as unknown as EuiDataGridColumnCellActionProps,
|
||||
servicesMock.toastNotifications,
|
||||
dataTableContextMock.valueToStringConverter
|
||||
)}
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'copyClipboardButton');
|
||||
await button.simulate('click');
|
||||
expect(mockCopyToClipboard).toHaveBeenCalledWith('jpg');
|
||||
});
|
||||
});
|
|
@ -9,14 +9,15 @@
|
|||
import React, { useContext } from 'react';
|
||||
import { EuiDataGridColumnCellActionProps } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
import { ToastsStart } from '@kbn/core/public';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { DiscoverGridContext, GridContext } from './discover_grid_context';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
import { copyValueToClipboard } from '../../utils/copy_value_to_clipboard';
|
||||
import { UnifiedDataTableContext, DataTableContext } from '../table_context';
|
||||
import { copyValueToClipboard } from '../utils/copy_value_to_clipboard';
|
||||
import { ValueToStringConverter } from '../types';
|
||||
|
||||
function onFilterCell(
|
||||
context: GridContext,
|
||||
context: DataTableContext,
|
||||
rowIndex: EuiDataGridColumnCellActionProps['rowIndex'],
|
||||
columnId: EuiDataGridColumnCellActionProps['columnId'],
|
||||
mode: '+' | '-'
|
||||
|
@ -35,8 +36,8 @@ export const FilterInBtn = ({
|
|||
rowIndex,
|
||||
columnId,
|
||||
}: EuiDataGridColumnCellActionProps) => {
|
||||
const context = useContext(DiscoverGridContext);
|
||||
const buttonTitle = i18n.translate('discover.grid.filterForAria', {
|
||||
const context = useContext(UnifiedDataTableContext);
|
||||
const buttonTitle = i18n.translate('unifiedDataTable.grid.filterForAria', {
|
||||
defaultMessage: 'Filter for this {value}',
|
||||
values: { value: columnId },
|
||||
});
|
||||
|
@ -51,7 +52,7 @@ export const FilterInBtn = ({
|
|||
title={buttonTitle}
|
||||
data-test-subj="filterForButton"
|
||||
>
|
||||
{i18n.translate('discover.grid.filterFor', {
|
||||
{i18n.translate('unifiedDataTable.grid.filterFor', {
|
||||
defaultMessage: 'Filter for',
|
||||
})}
|
||||
</Component>
|
||||
|
@ -63,8 +64,8 @@ export const FilterOutBtn = ({
|
|||
rowIndex,
|
||||
columnId,
|
||||
}: EuiDataGridColumnCellActionProps) => {
|
||||
const context = useContext(DiscoverGridContext);
|
||||
const buttonTitle = i18n.translate('discover.grid.filterOutAria', {
|
||||
const context = useContext(UnifiedDataTableContext);
|
||||
const buttonTitle = i18n.translate('unifiedDataTable.grid.filterOutAria', {
|
||||
defaultMessage: 'Filter out this {value}',
|
||||
values: { value: columnId },
|
||||
});
|
||||
|
@ -79,18 +80,19 @@ export const FilterOutBtn = ({
|
|||
title={buttonTitle}
|
||||
data-test-subj="filterOutButton"
|
||||
>
|
||||
{i18n.translate('discover.grid.filterOut', {
|
||||
{i18n.translate('unifiedDataTable.grid.filterOut', {
|
||||
defaultMessage: 'Filter out',
|
||||
})}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps) => {
|
||||
const { valueToStringConverter } = useContext(DiscoverGridContext);
|
||||
const { toastNotifications } = useDiscoverServices();
|
||||
|
||||
const buttonTitle = i18n.translate('discover.grid.copyClipboardButtonTitle', {
|
||||
export function buildCopyValueButton(
|
||||
{ Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps,
|
||||
toastNotifications: ToastsStart,
|
||||
valueToStringConverter: ValueToStringConverter
|
||||
) {
|
||||
const buttonTitle = i18n.translate('unifiedDataTable.grid.copyClipboardButtonTitle', {
|
||||
defaultMessage: 'Copy value of {column}',
|
||||
values: { column: columnId },
|
||||
});
|
||||
|
@ -101,8 +103,8 @@ export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCell
|
|||
copyValueToClipboard({
|
||||
rowIndex,
|
||||
columnId,
|
||||
toastNotifications,
|
||||
valueToStringConverter,
|
||||
toastNotifications,
|
||||
});
|
||||
}}
|
||||
iconType="copyClipboard"
|
||||
|
@ -110,13 +112,26 @@ export const CopyBtn = ({ Component, rowIndex, columnId }: EuiDataGridColumnCell
|
|||
title={buttonTitle}
|
||||
data-test-subj="copyClipboardButton"
|
||||
>
|
||||
{i18n.translate('discover.grid.copyCellValueButton', {
|
||||
{i18n.translate('unifiedDataTable.grid.copyCellValueButton', {
|
||||
defaultMessage: 'Copy value',
|
||||
})}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
|
||||
export function buildCellActions(field: DataViewField, onFilter?: DocViewFilterFn) {
|
||||
return [...(onFilter && field.filterable ? [FilterInBtn, FilterOutBtn] : []), CopyBtn];
|
||||
}
|
||||
|
||||
export function buildCellActions(
|
||||
field: DataViewField,
|
||||
toastNotifications: ToastsStart,
|
||||
valueToStringConverter: ValueToStringConverter,
|
||||
onFilter?: DocViewFilterFn
|
||||
) {
|
||||
return [
|
||||
...(onFilter && field.filterable ? [FilterInBtn, FilterOutBtn] : []),
|
||||
({ Component, rowIndex, columnId }: EuiDataGridColumnCellActionProps) =>
|
||||
buildCopyValueButton(
|
||||
{ Component, rowIndex, columnId } as EuiDataGridColumnCellActionProps,
|
||||
toastNotifications,
|
||||
valueToStringConverter
|
||||
),
|
||||
];
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`returns the \`JsonCodeEditor\` component 1`] = `
|
||||
<JsonCodeEditorCommon
|
||||
hideCopyButton={true}
|
||||
jsonValue="{
|
||||
\\"_index\\": \\"test\\",
|
||||
\\"_type\\": \\"doc\\",
|
||||
\\"_id\\": \\"foo\\",
|
||||
\\"_score\\": 1,
|
||||
\\"_source\\": {
|
||||
\\"test\\": 123
|
||||
}
|
||||
}"
|
||||
onEditorDidMount={[Function]}
|
||||
/>
|
||||
`;
|
|
@ -0,0 +1,3 @@
|
|||
.unifiedDataTableJsonEditor {
|
||||
width: 100%;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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 React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import JsonCodeEditor from './json_code_editor';
|
||||
|
||||
it('returns the `JsonCodeEditor` component', () => {
|
||||
const value = {
|
||||
_index: 'test',
|
||||
_type: 'doc',
|
||||
_id: 'foo',
|
||||
_score: 1,
|
||||
_source: { test: 123 },
|
||||
};
|
||||
expect(shallow(<JsonCodeEditor json={value} />)).toMatchSnapshot();
|
||||
});
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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 './json_code_editor.scss';
|
||||
|
||||
import React from 'react';
|
||||
import { JsonCodeEditorCommon } from './json_code_editor_common';
|
||||
|
||||
export interface JsonCodeEditorProps {
|
||||
json: Record<string, unknown>;
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
hasLineNumbers?: boolean;
|
||||
}
|
||||
|
||||
// Required for usage in React.lazy
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default function JsonCodeEditor({
|
||||
json,
|
||||
width,
|
||||
height,
|
||||
hasLineNumbers,
|
||||
}: JsonCodeEditorProps) {
|
||||
const jsonValue = JSON.stringify(json, null, 2);
|
||||
|
||||
return (
|
||||
<JsonCodeEditorCommon
|
||||
jsonValue={jsonValue}
|
||||
width={width}
|
||||
height={height}
|
||||
hasLineNumbers={hasLineNumbers}
|
||||
onEditorDidMount={() => void 0}
|
||||
hideCopyButton={true}
|
||||
/>
|
||||
);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* 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 './json_code_editor.scss';
|
||||
|
||||
import React from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { monaco, XJsonLang } from '@kbn/monaco';
|
||||
import { EuiButtonEmpty, EuiCopy, EuiFlexGroup, EuiFlexItem, EuiSpacer } from '@elastic/eui';
|
||||
import { CodeEditor } from '@kbn/code-editor';
|
||||
const codeEditorAriaLabel = i18n.translate('unifiedDataTable.json.codeEditorAriaLabel', {
|
||||
defaultMessage: 'Read only JSON view of an elasticsearch document',
|
||||
});
|
||||
const copyToClipboardLabel = i18n.translate('unifiedDataTable.json.copyToClipboardLabel', {
|
||||
defaultMessage: 'Copy to clipboard',
|
||||
});
|
||||
|
||||
interface JsonCodeEditorCommonProps {
|
||||
jsonValue: string;
|
||||
onEditorDidMount: (editor: monaco.editor.IStandaloneCodeEditor) => void;
|
||||
width?: string | number;
|
||||
height?: string | number;
|
||||
hasLineNumbers?: boolean;
|
||||
hideCopyButton?: boolean;
|
||||
}
|
||||
|
||||
export const JsonCodeEditorCommon = ({
|
||||
jsonValue,
|
||||
width,
|
||||
height,
|
||||
hasLineNumbers,
|
||||
onEditorDidMount,
|
||||
hideCopyButton,
|
||||
}: JsonCodeEditorCommonProps) => {
|
||||
if (jsonValue === '') {
|
||||
return null;
|
||||
}
|
||||
|
||||
const codeEditor = (
|
||||
<CodeEditor
|
||||
languageId={XJsonLang.ID}
|
||||
width={width}
|
||||
height={height}
|
||||
value={jsonValue || ''}
|
||||
editorDidMount={onEditorDidMount}
|
||||
aria-label={codeEditorAriaLabel}
|
||||
options={{
|
||||
automaticLayout: true,
|
||||
fontSize: 12,
|
||||
lineNumbers: hasLineNumbers ? 'on' : 'off',
|
||||
minimap: {
|
||||
enabled: false,
|
||||
},
|
||||
overviewRulerBorder: false,
|
||||
readOnly: true,
|
||||
scrollbar: {
|
||||
alwaysConsumeMouseWheel: false,
|
||||
},
|
||||
scrollBeyondLastLine: false,
|
||||
wordWrap: 'on',
|
||||
wrappingIndent: 'indent',
|
||||
}}
|
||||
/>
|
||||
);
|
||||
if (hideCopyButton) {
|
||||
return codeEditor;
|
||||
}
|
||||
return (
|
||||
<EuiFlexGroup className="unifiedDataTableJsonEditor" direction="column" gutterSize="s">
|
||||
<EuiFlexItem>
|
||||
<EuiSpacer size="s" />
|
||||
<div className="eui-textRight">
|
||||
<EuiCopy textToCopy={jsonValue}>
|
||||
{(copy) => (
|
||||
<EuiButtonEmpty size="xs" flush="right" iconType="copyClipboard" onClick={copy}>
|
||||
{copyToClipboardLabel}
|
||||
</EuiButtonEmpty>
|
||||
)}
|
||||
</EuiCopy>
|
||||
</div>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>{codeEditor}</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
export const JSONCodeEditorCommonMemoized = React.memo((props: JsonCodeEditorCommonProps) => {
|
||||
return <JsonCodeEditorCommon {...props} />;
|
||||
});
|
|
@ -5,11 +5,17 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { EuiDataGridStyle } from '@elastic/eui';
|
||||
|
||||
// data types
|
||||
export const DEFAULT_ROWS_PER_PAGE = 100;
|
||||
export const MAX_LOADED_GRID_ROWS = 10000;
|
||||
|
||||
export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500];
|
||||
|
||||
export const defaultMonacoEditorWidth = 370;
|
||||
export const defaultTimeColumnWidth = 210;
|
||||
export const kibanaJSON = 'kibana-json';
|
||||
|
||||
export const GRID_STYLE = {
|
||||
border: 'all',
|
||||
fontSize: 's',
|
||||
|
@ -17,12 +23,9 @@ export const GRID_STYLE = {
|
|||
rowHover: 'none',
|
||||
} as EuiDataGridStyle;
|
||||
|
||||
export const defaultTimeColumnWidth = 210;
|
||||
export const toolbarVisibility = {
|
||||
showColumnSelector: {
|
||||
allowHide: false,
|
||||
allowReorder: true,
|
||||
},
|
||||
};
|
||||
|
||||
export const defaultMonacoEditorWidth = 370;
|
|
@ -9,8 +9,8 @@
|
|||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { useColumns } from './use_data_grid_columns';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { configMock } from '../__mocks__/config';
|
||||
import { dataViewsMock } from '../__mocks__/data_views';
|
||||
import { configMock } from '../../__mocks__/config';
|
||||
import { dataViewsMock } from '../../__mocks__/data_views';
|
||||
import { Capabilities } from '@kbn/core/types';
|
||||
|
||||
describe('useColumns', () => {
|
|
@ -9,32 +9,30 @@
|
|||
import { useEffect, useMemo, useState } from 'react';
|
||||
import type { DataView, DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
|
||||
import { Capabilities, IUiSettingsClient } from '@kbn/core/public';
|
||||
import { Capabilities } from '@kbn/core/public';
|
||||
import { isEqual } from 'lodash';
|
||||
import { DiscoverAppStateContainer } from '../application/main/services/discover_app_state_container';
|
||||
import { GetStateReturn as ContextGetStateReturn } from '../application/context/services/context_state';
|
||||
import { getStateColumnActions } from '../components/doc_table/actions/columns';
|
||||
import { getStateColumnActions } from '../components/actions/columns';
|
||||
|
||||
interface UseColumnsProps {
|
||||
capabilities: Capabilities;
|
||||
config: IUiSettingsClient;
|
||||
dataView: DataView;
|
||||
dataViews: DataViewsContract;
|
||||
useNewFieldsApi: boolean;
|
||||
setAppState: DiscoverAppStateContainer['update'] | ContextGetStateReturn['setAppState'];
|
||||
setAppState: (state: { columns: string[]; sort?: string[][] }) => void;
|
||||
columns?: string[];
|
||||
sort?: string[][];
|
||||
defaultOrder?: string;
|
||||
}
|
||||
|
||||
export const useColumns = ({
|
||||
capabilities,
|
||||
config,
|
||||
dataView,
|
||||
dataViews,
|
||||
setAppState,
|
||||
useNewFieldsApi,
|
||||
columns,
|
||||
sort,
|
||||
defaultOrder = 'desc',
|
||||
}: UseColumnsProps) => {
|
||||
const [usedColumns, setUsedColumns] = useState(getColumns(columns, useNewFieldsApi));
|
||||
useEffect(() => {
|
||||
|
@ -48,15 +46,24 @@ export const useColumns = ({
|
|||
() =>
|
||||
getStateColumnActions({
|
||||
capabilities,
|
||||
config,
|
||||
dataView,
|
||||
dataViews,
|
||||
setAppState,
|
||||
useNewFieldsApi,
|
||||
columns: usedColumns,
|
||||
sort,
|
||||
defaultOrder,
|
||||
}),
|
||||
[capabilities, config, dataView, dataViews, setAppState, sort, useNewFieldsApi, usedColumns]
|
||||
[
|
||||
capabilities,
|
||||
dataView,
|
||||
dataViews,
|
||||
defaultOrder,
|
||||
setAppState,
|
||||
sort,
|
||||
useNewFieldsApi,
|
||||
usedColumns,
|
||||
]
|
||||
);
|
||||
|
||||
return {
|
|
@ -0,0 +1,77 @@
|
|||
/*
|
||||
* 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 { renderHook } from '@testing-library/react-hooks';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { LocalStorageMock } from '../../__mocks__/local_storage_mock';
|
||||
import { useRowHeightsOptions } from './use_row_heights_options';
|
||||
|
||||
const CONFIG_ROW_HEIGHT = 3;
|
||||
|
||||
describe('useRowHeightsOptions', () => {
|
||||
test('should apply rowHeight from savedSearch', () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useRowHeightsOptions({
|
||||
rowHeightState: 2,
|
||||
storage: new LocalStorageMock({}) as unknown as Storage,
|
||||
consumer: 'discover',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({ lineCount: 2 });
|
||||
});
|
||||
|
||||
test('should apply rowHeight from local storage', () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useRowHeightsOptions({
|
||||
storage: new LocalStorageMock({
|
||||
['discover:dataGridRowHeight']: {
|
||||
previousRowHeight: 5,
|
||||
previousConfigRowHeight: 3,
|
||||
},
|
||||
}) as unknown as Storage,
|
||||
consumer: 'discover',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({ lineCount: 5 });
|
||||
});
|
||||
|
||||
test('should apply rowHeight from configRowHeight', () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useRowHeightsOptions({
|
||||
consumer: 'discover',
|
||||
configRowHeight: 3,
|
||||
storage: new LocalStorageMock({}) as unknown as Storage,
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({
|
||||
lineCount: CONFIG_ROW_HEIGHT,
|
||||
});
|
||||
});
|
||||
|
||||
test('should apply rowHeight from uiSettings instead of local storage value, since uiSettings has been changed', () => {
|
||||
const { result } = renderHook(() => {
|
||||
return useRowHeightsOptions({
|
||||
storage: new LocalStorageMock({
|
||||
['discover:dataGridRowHeight']: {
|
||||
previousRowHeight: 4,
|
||||
// different from uiSettings (config), now user changed it to 3, but prev was 4
|
||||
previousConfigRowHeight: 4,
|
||||
},
|
||||
}) as unknown as Storage,
|
||||
consumer: 'discover',
|
||||
});
|
||||
});
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({
|
||||
lineCount: CONFIG_ROW_HEIGHT,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,10 +7,9 @@
|
|||
*/
|
||||
|
||||
import type { EuiDataGridRowHeightOption, EuiDataGridRowHeightsOptions } from '@elastic/eui';
|
||||
import type { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { useMemo } from 'react';
|
||||
import { ROW_HEIGHT_OPTION } from '@kbn/discover-utils';
|
||||
import { isValidRowHeight } from '../utils/validate_row_height';
|
||||
import { useDiscoverServices } from './use_discover_services';
|
||||
import {
|
||||
DataGridOptionsRecord,
|
||||
getStoredRowHeight,
|
||||
|
@ -20,6 +19,9 @@ import {
|
|||
interface UseRowHeightProps {
|
||||
rowHeightState?: number;
|
||||
onUpdateRowHeight?: (rowHeight: number) => void;
|
||||
storage: Storage;
|
||||
configRowHeight?: number;
|
||||
consumer: string;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -30,6 +32,7 @@ interface UseRowHeightProps {
|
|||
*/
|
||||
const SINGLE_ROW_HEIGHT_OPTION = 0;
|
||||
const AUTO_ROW_HEIGHT_OPTION = -1;
|
||||
const DEFAULT_ROW_HEIGHT_OPTION = 3;
|
||||
|
||||
/**
|
||||
* Converts rowHeight of EuiDataGrid to rowHeight number (-1 to 20)
|
||||
|
@ -57,12 +60,15 @@ const deserializeRowHeight = (number: number): EuiDataGridRowHeightOption | unde
|
|||
return { lineCount: number }; // custom
|
||||
};
|
||||
|
||||
export const useRowHeightsOptions = ({ rowHeightState, onUpdateRowHeight }: UseRowHeightProps) => {
|
||||
const { storage, uiSettings } = useDiscoverServices();
|
||||
|
||||
export const useRowHeightsOptions = ({
|
||||
rowHeightState,
|
||||
onUpdateRowHeight,
|
||||
storage,
|
||||
configRowHeight = DEFAULT_ROW_HEIGHT_OPTION,
|
||||
consumer,
|
||||
}: UseRowHeightProps) => {
|
||||
return useMemo((): EuiDataGridRowHeightsOptions => {
|
||||
const rowHeightFromLS = getStoredRowHeight(storage);
|
||||
const configRowHeight = uiSettings.get(ROW_HEIGHT_OPTION);
|
||||
const rowHeightFromLS = getStoredRowHeight(storage, consumer);
|
||||
|
||||
const configHasNotChanged = (
|
||||
localStorageRecord: DataGridOptionsRecord | null
|
||||
|
@ -83,9 +89,9 @@ export const useRowHeightsOptions = ({ rowHeightState, onUpdateRowHeight }: UseR
|
|||
lineHeight: '1.6em',
|
||||
onChange: ({ defaultHeight: newRowHeight }: EuiDataGridRowHeightsOptions) => {
|
||||
const newSerializedRowHeight = serializeRowHeight(newRowHeight);
|
||||
updateStoredRowHeight(newSerializedRowHeight, configRowHeight, storage);
|
||||
updateStoredRowHeight(newSerializedRowHeight, configRowHeight, storage, consumer);
|
||||
onUpdateRowHeight?.(newSerializedRowHeight);
|
||||
},
|
||||
};
|
||||
}, [rowHeightState, uiSettings, storage, onUpdateRowHeight]);
|
||||
}, [storage, consumer, rowHeightState, configRowHeight, onUpdateRowHeight]);
|
||||
};
|
|
@ -9,10 +9,10 @@
|
|||
import React from 'react';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import type { ValueToStringConverter } from '../../types';
|
||||
import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import type { ValueToStringConverter } from './types';
|
||||
|
||||
export interface GridContext {
|
||||
export interface DataTableContext {
|
||||
expanded?: DataTableRecord | undefined;
|
||||
setExpanded?: (hit?: DataTableRecord) => void;
|
||||
rows: DataTableRecord[];
|
||||
|
@ -22,8 +22,9 @@ export interface GridContext {
|
|||
selectedDocs: string[];
|
||||
setSelectedDocs: (selected: string[]) => void;
|
||||
valueToStringConverter: ValueToStringConverter;
|
||||
componentsTourSteps?: Record<string, string>;
|
||||
}
|
||||
|
||||
const defaultContext = {} as unknown as GridContext;
|
||||
const defaultContext = {} as unknown as DataTableContext;
|
||||
|
||||
export const DiscoverGridContext = React.createContext<GridContext>(defaultContext);
|
||||
export const UnifiedDataTableContext = React.createContext<DataTableContext>(defaultContext);
|
|
@ -6,19 +6,19 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { DatatableColumn } from '@kbn/expressions-plugin/common';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings';
|
||||
/**
|
||||
* User configurable state of data grid, persisted in saved search
|
||||
*/
|
||||
export interface UnifiedDataTableSettings {
|
||||
columns?: Record<string, UnifiedDataTableSettingsColumn>;
|
||||
}
|
||||
|
||||
export interface UnifiedDataTableSettingsColumn {
|
||||
width?: number;
|
||||
}
|
||||
|
||||
export type ValueToStringConverter = (
|
||||
rowIndex: number,
|
||||
columnId: string,
|
||||
options?: { compatibleWithCSV?: boolean }
|
||||
) => { formattedString: string; withFormula: boolean };
|
||||
|
||||
export interface RecordsFetchResponse {
|
||||
records: DataTableRecord[];
|
||||
textBasedQueryColumns?: DatatableColumn[];
|
||||
textBasedHeaderWarning?: string;
|
||||
interceptedWarnings?: SearchResponseInterceptedWarning[];
|
||||
}
|
|
@ -6,8 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { dataViewWithTimefieldMock } from '../../__mocks__/data_view_with_timefield';
|
||||
import { getDisplayedColumns } from './columns';
|
||||
import { dataViewWithTimefieldMock } from '../__mocks__/data_view_with_timefield';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
|
||||
describe('getDisplayedColumns', () => {
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
|
||||
// We store this outside the function as a constant, so we're not creating a new array every time
|
||||
// the function is returning this. A changing array might cause the data grid to think it got
|
|
@ -6,16 +6,16 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { discoverGridContextComplexMock, discoverGridContextMock } from '../__mocks__/grid_context';
|
||||
import { discoverServiceMock } from '../__mocks__/services';
|
||||
import { dataTableContextComplexMock, dataTableContextMock } from '../../__mocks__/table_context';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import { convertValueToString, convertNameToString } from './convert_value_to_string';
|
||||
|
||||
describe('convertValueToString', () => {
|
||||
it('should convert a keyword value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'keyword_key',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -28,9 +28,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a text value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'text_message',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -43,9 +43,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a text value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'text_message',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -58,9 +58,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a multiline text value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'text_message',
|
||||
rowIndex: 1,
|
||||
options: {
|
||||
|
@ -74,9 +74,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a number value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'number_price',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -89,9 +89,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a date value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'date',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -104,9 +104,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a date nanos value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'date_nanos',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -119,9 +119,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a date nanos value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'date_nanos',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -134,9 +134,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a boolean value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'bool_enabled',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -149,9 +149,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a binary value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'binary_blob',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -164,9 +164,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a binary value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'binary_blob',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -179,9 +179,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert an object value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'object_user.first',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -194,9 +194,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a nested value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'nested_user',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -211,9 +211,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a flattened value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'flattened_labels',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -226,9 +226,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a range value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'range_time_frame',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -243,9 +243,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a rank features value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'rank_features',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -258,9 +258,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a histogram value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'histogram',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -273,9 +273,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a IP value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'ip_addr',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -288,9 +288,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a IP value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'ip_addr',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -303,9 +303,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a version value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'version',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -318,9 +318,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a version value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'version',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -333,9 +333,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a vector value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'vector',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -348,9 +348,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a geo point value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'geo_point',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -363,9 +363,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a geo point object value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'geo_point',
|
||||
rowIndex: 1,
|
||||
options: {
|
||||
|
@ -378,9 +378,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert an array value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'array_tags',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -393,9 +393,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a shape value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'geometry',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -410,9 +410,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a runtime value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'runtime_number',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -425,9 +425,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a scripted value to text', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'scripted_string',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -440,9 +440,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should convert a scripted value to text (not for CSV)', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'scripted_string',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -455,9 +455,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should return an empty string and not fail', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'unknown',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -470,9 +470,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should return an empty string when rowIndex is out of range', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'unknown',
|
||||
rowIndex: -1,
|
||||
options: {
|
||||
|
@ -485,9 +485,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should return _source value', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextMock.rows,
|
||||
dataView: discoverGridContextMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextMock.rows,
|
||||
dataView: dataTableContextMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: '_source',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -508,9 +508,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should return a formatted _source value', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextMock.rows,
|
||||
dataView: discoverGridContextMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextMock.rows,
|
||||
dataView: dataTableContextMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: '_source',
|
||||
rowIndex: 0,
|
||||
options: {
|
||||
|
@ -525,9 +525,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should escape formula', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'array_tags',
|
||||
rowIndex: 1,
|
||||
options: {
|
||||
|
@ -539,9 +539,9 @@ describe('convertValueToString', () => {
|
|||
expect(result.withFormula).toBe(true);
|
||||
|
||||
const result2 = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'scripted_string',
|
||||
rowIndex: 1,
|
||||
options: {
|
||||
|
@ -555,9 +555,9 @@ describe('convertValueToString', () => {
|
|||
|
||||
it('should not escape formulas when not for CSV', () => {
|
||||
const result = convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
columnId: 'array_tags',
|
||||
rowIndex: 1,
|
||||
options: {
|
|
@ -6,9 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { cellHasFormulas, createEscapeValue } from '@kbn/data-plugin/common';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { formatFieldValue } from '@kbn/discover-utils';
|
||||
|
|
@ -6,8 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { discoverGridContextComplexMock } from '../__mocks__/grid_context';
|
||||
import { discoverServiceMock } from '../__mocks__/services';
|
||||
import { dataTableContextComplexMock } from '../../__mocks__/table_context';
|
||||
import { servicesMock } from '../../__mocks__/services';
|
||||
import {
|
||||
copyValueToClipboard,
|
||||
copyColumnNameToClipboard,
|
||||
|
@ -22,9 +22,9 @@ const warn = jest.spyOn(console, 'warn').mockImplementation(() => {});
|
|||
describe('copyValueToClipboard', () => {
|
||||
const valueToStringConverter: ValueToStringConverter = (rowIndex, columnId, options) =>
|
||||
convertValueToString({
|
||||
rows: discoverGridContextComplexMock.rows,
|
||||
dataView: discoverGridContextComplexMock.dataView,
|
||||
fieldFormats: discoverServiceMock.fieldFormats,
|
||||
rows: dataTableContextComplexMock.rows,
|
||||
dataView: dataTableContextComplexMock.dataView,
|
||||
fieldFormats: servicesMock.fieldFormats,
|
||||
rowIndex,
|
||||
columnId,
|
||||
options,
|
||||
|
@ -39,6 +39,10 @@ describe('copyValueToClipboard', () => {
|
|||
},
|
||||
writable: true,
|
||||
});
|
||||
Object.defineProperty(window, 'sessionStorage', {
|
||||
value: { clear: jest.fn() },
|
||||
writable: true,
|
||||
});
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
|
@ -50,7 +54,7 @@ describe('copyValueToClipboard', () => {
|
|||
it('should copy a value to clipboard', () => {
|
||||
execCommandMock.mockImplementationOnce(() => true);
|
||||
const result = copyValueToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnId: 'keyword_key',
|
||||
rowIndex: 0,
|
||||
valueToStringConverter,
|
||||
|
@ -59,7 +63,7 @@ describe('copyValueToClipboard', () => {
|
|||
expect(result).toBe('abcd1');
|
||||
expect(execCommandMock).toHaveBeenCalledWith('copy');
|
||||
expect(warn).not.toHaveBeenCalled();
|
||||
expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
title: 'Copied to clipboard',
|
||||
});
|
||||
});
|
||||
|
@ -68,7 +72,7 @@ describe('copyValueToClipboard', () => {
|
|||
execCommandMock.mockImplementationOnce(() => false);
|
||||
|
||||
const result = copyValueToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnId: 'keyword_key',
|
||||
rowIndex: 0,
|
||||
valueToStringConverter,
|
||||
|
@ -77,7 +81,7 @@ describe('copyValueToClipboard', () => {
|
|||
expect(result).toBe(null);
|
||||
expect(execCommandMock).toHaveBeenCalledWith('copy');
|
||||
expect(warn).toHaveBeenCalledWith('Unable to copy to clipboard.');
|
||||
expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
title: 'Unable to copy to clipboard in this browser',
|
||||
});
|
||||
});
|
||||
|
@ -85,13 +89,13 @@ describe('copyValueToClipboard', () => {
|
|||
it('should copy a column name to clipboard', () => {
|
||||
execCommandMock.mockImplementationOnce(() => true);
|
||||
const result = copyColumnNameToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnDisplayName: 'text_message',
|
||||
});
|
||||
|
||||
expect(result).toBe('"text_message"');
|
||||
expect(execCommandMock).toHaveBeenCalledWith('copy');
|
||||
expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
title: 'Copied to clipboard',
|
||||
});
|
||||
});
|
||||
|
@ -99,14 +103,14 @@ describe('copyValueToClipboard', () => {
|
|||
it('should inform when copy a column name to clipboard failed', () => {
|
||||
execCommandMock.mockImplementationOnce(() => false);
|
||||
const result = copyColumnNameToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnDisplayName: 'text_message',
|
||||
});
|
||||
|
||||
expect(result).toBe(null);
|
||||
expect(execCommandMock).toHaveBeenCalledWith('copy');
|
||||
expect(warn).toHaveBeenCalledWith('Unable to copy to clipboard.');
|
||||
expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
title: 'Unable to copy to clipboard in this browser',
|
||||
});
|
||||
});
|
||||
|
@ -115,7 +119,7 @@ describe('copyValueToClipboard', () => {
|
|||
execCommandMock.mockImplementationOnce(() => true);
|
||||
|
||||
const result = await copyColumnValuesToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnId: 'bool_enabled',
|
||||
columnDisplayName: 'custom_bool_enabled',
|
||||
rowsCount: 2,
|
||||
|
@ -126,7 +130,7 @@ describe('copyValueToClipboard', () => {
|
|||
expect(global.window.navigator.clipboard.writeText).toHaveBeenCalledWith(
|
||||
'"custom_bool_enabled"\nfalse\ntrue'
|
||||
);
|
||||
expect(discoverServiceMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addInfo).toHaveBeenCalledWith({
|
||||
title: 'Values of "custom_bool_enabled" column copied to clipboard',
|
||||
});
|
||||
});
|
||||
|
@ -134,7 +138,7 @@ describe('copyValueToClipboard', () => {
|
|||
it('should copy column values to clipboard with a warning', async () => {
|
||||
execCommandMock.mockImplementationOnce(() => true);
|
||||
const result = await copyColumnValuesToClipboard({
|
||||
toastNotifications: discoverServiceMock.toastNotifications,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
columnId: 'scripted_string',
|
||||
columnDisplayName: 'custom_scripted_string',
|
||||
rowsCount: 2,
|
||||
|
@ -142,7 +146,7 @@ describe('copyValueToClipboard', () => {
|
|||
});
|
||||
|
||||
expect(result).toBe('"custom_scripted_string"\n"hi there"\n"\'=1+2"";=1+2"');
|
||||
expect(discoverServiceMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
expect(servicesMock.toastNotifications.addWarning).toHaveBeenCalledWith({
|
||||
title: 'Values of "custom_scripted_string" column copied to clipboard',
|
||||
text: 'Values may contain formulas that are escaped.',
|
||||
});
|
|
@ -13,12 +13,12 @@ import type { ValueToStringConverter } from '../types';
|
|||
import { convertNameToString } from './convert_value_to_string';
|
||||
|
||||
const WARNING_FOR_FORMULAS = i18n.translate(
|
||||
'discover.grid.copyEscapedValueWithFormulasToClipboardWarningText',
|
||||
'unifiedDataTable.copyEscapedValueWithFormulasToClipboardWarningText',
|
||||
{
|
||||
defaultMessage: 'Values may contain formulas that are escaped.',
|
||||
}
|
||||
);
|
||||
const COPY_FAILED_ERROR_MESSAGE = i18n.translate('discover.grid.copyFailedErrorText', {
|
||||
const COPY_FAILED_ERROR_MESSAGE = i18n.translate('unifiedDataTable.copyFailedErrorText', {
|
||||
defaultMessage: 'Unable to copy to clipboard in this browser',
|
||||
});
|
||||
|
||||
|
@ -46,7 +46,7 @@ export const copyValueToClipboard = ({
|
|||
return null;
|
||||
}
|
||||
|
||||
const toastTitle = i18n.translate('discover.grid.copyValueToClipboard.toastTitle', {
|
||||
const toastTitle = i18n.translate('unifiedDataTable.copyValueToClipboard.toastTitle', {
|
||||
defaultMessage: 'Copied to clipboard',
|
||||
});
|
||||
|
||||
|
@ -105,7 +105,7 @@ export const copyColumnValuesToClipboard = async ({
|
|||
return null;
|
||||
}
|
||||
|
||||
const toastTitle = i18n.translate('discover.grid.copyColumnValuesToClipboard.toastTitle', {
|
||||
const toastTitle = i18n.translate('unifiedDataTable.copyColumnValuesToClipboard.toastTitle', {
|
||||
defaultMessage: 'Values of "{column}" column copied to clipboard',
|
||||
values: { column: columnDisplayName },
|
||||
});
|
||||
|
@ -143,7 +143,7 @@ export const copyColumnNameToClipboard = ({
|
|||
return null;
|
||||
}
|
||||
|
||||
const toastTitle = i18n.translate('discover.grid.copyColumnNameToClipboard.toastTitle', {
|
||||
const toastTitle = i18n.translate('unifiedDataTable.copyColumnNameToClipboard.toastTitle', {
|
||||
defaultMessage: 'Copied to clipboard',
|
||||
});
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
|
||||
export const getFieldCapabilities = (dataView: DataView, field: DataViewField) => {
|
||||
const isRuntimeField = Boolean(dataView.getFieldByName(field.name)?.runtimeField);
|
|
@ -13,9 +13,38 @@ import { findTestSubject } from '@elastic/eui/lib/test';
|
|||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { getRenderCellValueFn } from './get_render_cell_value';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { CodeEditorProps, KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { buildDataTableRecord } from '@kbn/discover-utils';
|
||||
import type { EsHitRecord } from '@kbn/discover-utils/types';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
|
||||
jest.mock('@kbn/code-editor', () => {
|
||||
const original = jest.requireActual('@kbn/code-editor');
|
||||
|
||||
const CodeEditorMock = (props: CodeEditorProps) => (
|
||||
<input
|
||||
data-test-subj={'mockCodeEditor'}
|
||||
data-value={props.value}
|
||||
value={props.value}
|
||||
onChange={jest.fn()}
|
||||
/>
|
||||
);
|
||||
|
||||
return {
|
||||
...original,
|
||||
CodeEditor: CodeEditorMock,
|
||||
};
|
||||
});
|
||||
|
||||
window.matchMedia = jest.fn().mockImplementation((query) => {
|
||||
return {
|
||||
matches: false,
|
||||
media: query,
|
||||
onchange: null,
|
||||
addListener: jest.fn(),
|
||||
removeListener: jest.fn(),
|
||||
};
|
||||
});
|
||||
|
||||
const mockServices = {
|
||||
settings: {
|
||||
|
@ -34,14 +63,6 @@ const mockServices = {
|
|||
},
|
||||
};
|
||||
|
||||
jest.mock('../../hooks/use_discover_services', () => {
|
||||
const originalModule = jest.requireActual('../../hooks/use_discover_services');
|
||||
return {
|
||||
...originalModule,
|
||||
useDiscoverServices: () => mockServices,
|
||||
};
|
||||
});
|
||||
|
||||
const rowsSource: EsHitRecord[] = [
|
||||
{
|
||||
_id: '1',
|
||||
|
@ -82,18 +103,19 @@ const rowsFieldsWithTopLevelObject: EsHitRecord[] = [
|
|||
|
||||
const build = (hit: EsHitRecord) => buildDataTableRecord(hit, dataViewMock);
|
||||
|
||||
describe('Discover grid cell rendering', function () {
|
||||
describe('Unified data table cell rendering', function () {
|
||||
it('renders bytes column correctly', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="bytes"
|
||||
|
@ -104,21 +126,22 @@ describe('Discover grid cell rendering', function () {
|
|||
/>
|
||||
);
|
||||
expect(component.html()).toMatchInlineSnapshot(
|
||||
`"<span class=\\"dscDiscoverGrid__cellValue\\">100</span>"`
|
||||
`"<span class=\\"unifiedDataTable__cellValue\\">100</span>"`
|
||||
);
|
||||
});
|
||||
|
||||
it('renders bytes column correctly using _source when details is true', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="bytes"
|
||||
|
@ -129,22 +152,23 @@ describe('Discover grid cell rendering', function () {
|
|||
/>
|
||||
);
|
||||
expect(component.html()).toMatchInlineSnapshot(
|
||||
`"<div class=\\"euiFlexGroup css-1h68cm-euiFlexGroup-none-flexStart-stretch-row\\"><div class=\\"euiFlexItem css-9sbomz-euiFlexItem-grow-1\\"><span class=\\"dscDiscoverGrid__cellPopoverValue eui-textBreakWord\\">100</span></div><div class=\\"euiFlexItem css-kpsrin-euiFlexItem-growZero\\"><button class=\\"euiButtonIcon css-9sj1hz-euiButtonIcon-xs-empty-primary\\" type=\\"button\\" aria-label=\\"Close popover\\" data-test-subj=\\"docTableClosePopover\\"><span data-euiicon-type=\\"cross\\" class=\\"euiButtonIcon__icon\\" aria-hidden=\\"true\\" color=\\"inherit\\"></span></button></div></div>"`
|
||||
`"<div class=\\"euiFlexGroup css-1h68cm-euiFlexGroup-none-flexStart-stretch-row\\"><div class=\\"euiFlexItem css-9sbomz-euiFlexItem-grow-1\\"><span class=\\"unifiedDataTable__cellPopoverValue eui-textBreakWord\\">100</span></div><div class=\\"euiFlexItem css-kpsrin-euiFlexItem-growZero\\"><button class=\\"euiButtonIcon css-9sj1hz-euiButtonIcon-xs-empty-primary\\" type=\\"button\\" aria-label=\\"Close popover\\" data-test-subj=\\"docTableClosePopover\\"><span data-euiicon-type=\\"cross\\" class=\\"euiButtonIcon__icon\\" aria-hidden=\\"true\\" color=\\"inherit\\"></span></button></div></div>"`
|
||||
);
|
||||
});
|
||||
|
||||
it('renders bytes column correctly using fields when details is true', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
closePopoverMockFn
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="bytes"
|
||||
|
@ -155,23 +179,24 @@ describe('Discover grid cell rendering', function () {
|
|||
/>
|
||||
);
|
||||
expect(component.html()).toMatchInlineSnapshot(
|
||||
`"<div class=\\"euiFlexGroup css-1h68cm-euiFlexGroup-none-flexStart-stretch-row\\"><div class=\\"euiFlexItem css-9sbomz-euiFlexItem-grow-1\\"><span class=\\"dscDiscoverGrid__cellPopoverValue eui-textBreakWord\\">100</span></div><div class=\\"euiFlexItem css-kpsrin-euiFlexItem-growZero\\"><button class=\\"euiButtonIcon css-9sj1hz-euiButtonIcon-xs-empty-primary\\" type=\\"button\\" aria-label=\\"Close popover\\" data-test-subj=\\"docTableClosePopover\\"><span data-euiicon-type=\\"cross\\" class=\\"euiButtonIcon__icon\\" aria-hidden=\\"true\\" color=\\"inherit\\"></span></button></div></div>"`
|
||||
`"<div class=\\"euiFlexGroup css-1h68cm-euiFlexGroup-none-flexStart-stretch-row\\"><div class=\\"euiFlexItem css-9sbomz-euiFlexItem-grow-1\\"><span class=\\"unifiedDataTable__cellPopoverValue eui-textBreakWord\\">100</span></div><div class=\\"euiFlexItem css-kpsrin-euiFlexItem-growZero\\"><button class=\\"euiButtonIcon css-9sj1hz-euiButtonIcon-xs-empty-primary\\" type=\\"button\\" aria-label=\\"Close popover\\" data-test-subj=\\"docTableClosePopover\\"><span data-euiicon-type=\\"cross\\" class=\\"euiButtonIcon__icon\\" aria-hidden=\\"true\\" color=\\"inherit\\"></span></button></div></div>"`
|
||||
);
|
||||
findTestSubject(component, 'docTableClosePopover').simulate('click');
|
||||
expect(closePopoverMockFn).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('renders _source column correctly', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="_source"
|
||||
|
@ -183,7 +208,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiDescriptionList
|
||||
className="dscDiscoverGrid__descriptionList dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__descriptionList unifiedDataTable__cellValue"
|
||||
compressed={true}
|
||||
type="inline"
|
||||
>
|
||||
|
@ -191,7 +216,7 @@ describe('Discover grid cell rendering', function () {
|
|||
extension
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": ".gz",
|
||||
|
@ -202,7 +227,7 @@ describe('Discover grid cell rendering', function () {
|
|||
bytesDisplayName
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": 100,
|
||||
|
@ -213,7 +238,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_index
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "test",
|
||||
|
@ -224,7 +249,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_score
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": 1,
|
||||
|
@ -236,16 +261,17 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders _source column correctly when isDetails is set to true', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="_source"
|
||||
|
@ -257,7 +283,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiFlexGroup
|
||||
className="dscDiscoverGrid__cellPopover"
|
||||
className="unifiedDataTable__cellPopover"
|
||||
direction="column"
|
||||
gutterSize="none"
|
||||
justifyContent="flexEnd"
|
||||
|
@ -285,7 +311,7 @@ describe('Discover grid cell rendering', function () {
|
|||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ForwardRef
|
||||
<JsonCodeEditor
|
||||
height={200}
|
||||
json={
|
||||
Object {
|
||||
|
@ -311,16 +337,17 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders fields-based column correctly', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="_source"
|
||||
|
@ -332,7 +359,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiDescriptionList
|
||||
className="dscDiscoverGrid__descriptionList dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__descriptionList unifiedDataTable__cellValue"
|
||||
compressed={true}
|
||||
type="inline"
|
||||
>
|
||||
|
@ -340,7 +367,7 @@ describe('Discover grid cell rendering', function () {
|
|||
extension
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -353,7 +380,7 @@ describe('Discover grid cell rendering', function () {
|
|||
bytesDisplayName
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -366,7 +393,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_index
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "test",
|
||||
|
@ -377,7 +404,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_score
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": 1,
|
||||
|
@ -389,17 +416,18 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('limits amount of rendered items', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
// this is the number of rendered items
|
||||
1,
|
||||
jest.fn()
|
||||
1
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="_source"
|
||||
|
@ -411,7 +439,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiDescriptionList
|
||||
className="dscDiscoverGrid__descriptionList dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__descriptionList unifiedDataTable__cellValue"
|
||||
compressed={true}
|
||||
type="inline"
|
||||
>
|
||||
|
@ -419,7 +447,7 @@ describe('Discover grid cell rendering', function () {
|
|||
extension
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -432,7 +460,7 @@ describe('Discover grid cell rendering', function () {
|
|||
bytesDisplayName
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -445,7 +473,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_index
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "test",
|
||||
|
@ -456,7 +484,7 @@ describe('Discover grid cell rendering', function () {
|
|||
_score
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": 1,
|
||||
|
@ -468,16 +496,17 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders fields-based column correctly when isDetails is set to true', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="_source"
|
||||
|
@ -489,7 +518,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiFlexGroup
|
||||
className="dscDiscoverGrid__cellPopover"
|
||||
className="unifiedDataTable__cellPopover"
|
||||
direction="column"
|
||||
gutterSize="none"
|
||||
justifyContent="flexEnd"
|
||||
|
@ -517,7 +546,7 @@ describe('Discover grid cell rendering', function () {
|
|||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ForwardRef
|
||||
<JsonCodeEditor
|
||||
height={200}
|
||||
json={
|
||||
Object {
|
||||
|
@ -548,16 +577,17 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('collect object fields and renders them like _source', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
(fieldName) => ['object.value', 'extension', 'bytes'].includes(fieldName),
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="object"
|
||||
|
@ -569,7 +599,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiDescriptionList
|
||||
className="dscDiscoverGrid__descriptionList dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__descriptionList unifiedDataTable__cellValue"
|
||||
compressed={true}
|
||||
type="inline"
|
||||
>
|
||||
|
@ -577,7 +607,7 @@ describe('Discover grid cell rendering', function () {
|
|||
object.value
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "100",
|
||||
|
@ -590,16 +620,17 @@ describe('Discover grid cell rendering', function () {
|
|||
|
||||
it('collect object fields and renders them like _source with fallback for unmapped', () => {
|
||||
(dataViewMock.getFieldByName as jest.Mock).mockReturnValueOnce(undefined);
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes', 'object.value'].includes(fieldName),
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="object"
|
||||
|
@ -611,7 +642,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiDescriptionList
|
||||
className="dscDiscoverGrid__descriptionList dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__descriptionList unifiedDataTable__cellValue"
|
||||
compressed={true}
|
||||
type="inline"
|
||||
>
|
||||
|
@ -619,7 +650,7 @@ describe('Discover grid cell rendering', function () {
|
|||
object.value
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "100",
|
||||
|
@ -632,16 +663,17 @@ describe('Discover grid cell rendering', function () {
|
|||
|
||||
it('collect object fields and renders them as json in details', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
100,
|
||||
closePopoverMockFn
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="object"
|
||||
|
@ -653,7 +685,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<EuiFlexGroup
|
||||
className="dscDiscoverGrid__cellPopover"
|
||||
className="unifiedDataTable__cellPopover"
|
||||
direction="column"
|
||||
gutterSize="none"
|
||||
justifyContent="flexEnd"
|
||||
|
@ -681,7 +713,7 @@ describe('Discover grid cell rendering', function () {
|
|||
</EuiFlexGroup>
|
||||
</EuiFlexItem>
|
||||
<EuiFlexItem>
|
||||
<ForwardRef
|
||||
<JsonCodeEditor
|
||||
height={200}
|
||||
json={
|
||||
Object {
|
||||
|
@ -699,17 +731,18 @@ describe('Discover grid cell rendering', function () {
|
|||
|
||||
it('renders a functional close button when CodeEditor is rendered', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
100,
|
||||
closePopoverMockFn
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={mockServices}>
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="object"
|
||||
|
@ -727,16 +760,17 @@ describe('Discover grid cell rendering', function () {
|
|||
|
||||
it('does not collect subfields when the the column is unmapped but part of fields response', () => {
|
||||
(dataViewMock.getFieldByName as jest.Mock).mockReturnValueOnce(undefined);
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="object.value"
|
||||
|
@ -748,7 +782,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<span
|
||||
className="dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__cellValue"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -761,16 +795,17 @@ describe('Discover grid cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders correctly when invalid row is given', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="bytes"
|
||||
|
@ -781,21 +816,22 @@ describe('Discover grid cell rendering', function () {
|
|||
/>
|
||||
);
|
||||
expect(component.html()).toMatchInlineSnapshot(
|
||||
`"<span class=\\"dscDiscoverGrid__cellValue\\">-</span>"`
|
||||
`"<span class=\\"unifiedDataTable__cellValue\\">-</span>"`
|
||||
);
|
||||
});
|
||||
|
||||
it('renders correctly when invalid column is given', () => {
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="bytes-invalid"
|
||||
|
@ -806,7 +842,7 @@ describe('Discover grid cell rendering', function () {
|
|||
/>
|
||||
);
|
||||
expect(component.html()).toMatchInlineSnapshot(
|
||||
`"<span class=\\"dscDiscoverGrid__cellValue\\">-</span>"`
|
||||
`"<span class=\\"unifiedDataTable__cellValue\\">-</span>"`
|
||||
);
|
||||
});
|
||||
|
||||
|
@ -824,16 +860,17 @@ describe('Discover grid cell rendering', function () {
|
|||
},
|
||||
},
|
||||
];
|
||||
const DiscoverGridCellValue = getRenderCellValueFn(
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsUnmapped.map(build),
|
||||
true,
|
||||
(fieldName) => ['unmapped'].includes(fieldName),
|
||||
100,
|
||||
jest.fn()
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const component = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="unmapped"
|
||||
|
@ -845,7 +882,7 @@ describe('Discover grid cell rendering', function () {
|
|||
);
|
||||
expect(component).toMatchInlineSnapshot(`
|
||||
<span
|
||||
className="dscDiscoverGrid__cellValue"
|
||||
className="unifiedDataTable__cellValue"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
|
@ -857,7 +894,7 @@ describe('Discover grid cell rendering', function () {
|
|||
`);
|
||||
|
||||
const componentWithDetails = shallow(
|
||||
<DiscoverGridCellValue
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
colIndex={0}
|
||||
columnId="unmapped"
|
||||
|
@ -875,7 +912,7 @@ describe('Discover grid cell rendering', function () {
|
|||
>
|
||||
<EuiFlexItem>
|
||||
<span
|
||||
className="dscDiscoverGrid__cellPopoverValue eui-textBreakWord"
|
||||
className="unifiedDataTable__cellPopoverValue eui-textBreakWord"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import React, { Fragment, useContext, useEffect, useMemo } from 'react';
|
||||
import React, { Fragment, useContext, useEffect } from 'react';
|
||||
import classnames from 'classnames';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { euiLightVars as themeLight, euiDarkVars as themeDark } from '@kbn/ui-theme';
|
||||
|
@ -20,19 +20,18 @@ import {
|
|||
EuiFlexGroup,
|
||||
EuiFlexItem,
|
||||
} from '@elastic/eui';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type {
|
||||
DataTableRecord,
|
||||
EsHitRecord,
|
||||
ShouldShowFieldInTableHandler,
|
||||
} from '@kbn/discover-utils/types';
|
||||
import { MAX_DOC_FIELDS_DISPLAYED, formatFieldValue, formatHit } from '@kbn/discover-utils';
|
||||
import { JsonCodeEditor } from '@kbn/unified-doc-viewer-plugin/public';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { defaultMonacoEditorWidth } from './constants';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
import { formatFieldValue, formatHit } from '@kbn/discover-utils';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
import { defaultMonacoEditorWidth } from '../constants';
|
||||
import JsonCodeEditor from '../components/json_code_editor/json_code_editor';
|
||||
|
||||
const CELL_CLASS = 'dscDiscoverGrid__cellValue';
|
||||
const CELL_CLASS = 'unifiedDataTable__cellValue';
|
||||
|
||||
export const getRenderCellValueFn =
|
||||
(
|
||||
|
@ -40,18 +39,42 @@ export const getRenderCellValueFn =
|
|||
rows: DataTableRecord[] | undefined,
|
||||
useNewFieldsApi: boolean,
|
||||
shouldShowFieldHandler: ShouldShowFieldInTableHandler,
|
||||
maxDocFieldsDisplayed: number,
|
||||
closePopover: () => void
|
||||
closePopover: () => void,
|
||||
fieldFormats: FieldFormatsStart,
|
||||
maxEntries: number,
|
||||
externalCustomRenderers?: Record<
|
||||
string,
|
||||
(props: EuiDataGridCellValueElementProps) => React.ReactNode
|
||||
>
|
||||
) =>
|
||||
({ rowIndex, columnId, isDetails, setCellProps }: EuiDataGridCellValueElementProps) => {
|
||||
const { uiSettings, fieldFormats } = useDiscoverServices();
|
||||
|
||||
const maxEntries = useMemo(() => uiSettings.get(MAX_DOC_FIELDS_DISPLAYED), [uiSettings]);
|
||||
|
||||
({
|
||||
rowIndex,
|
||||
columnId,
|
||||
isDetails,
|
||||
setCellProps,
|
||||
colIndex,
|
||||
isExpandable,
|
||||
isExpanded,
|
||||
}: EuiDataGridCellValueElementProps) => {
|
||||
if (!!externalCustomRenderers && !!externalCustomRenderers[columnId]) {
|
||||
return (
|
||||
<>
|
||||
{externalCustomRenderers[columnId]({
|
||||
rowIndex,
|
||||
columnId,
|
||||
isDetails,
|
||||
setCellProps,
|
||||
isExpandable,
|
||||
isExpanded,
|
||||
colIndex,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
const row = rows ? rows[rowIndex] : undefined;
|
||||
|
||||
const field = dataView.fields.getByName(columnId);
|
||||
const ctx = useContext(DiscoverGridContext);
|
||||
const ctx = useContext(UnifiedDataTableContext);
|
||||
|
||||
useEffect(() => {
|
||||
if (row?.isAnchor) {
|
||||
|
@ -102,7 +125,7 @@ export const getRenderCellValueFn =
|
|||
const pairs = useTopLevelObjectColumns
|
||||
? getTopLevelObjectPairs(row.raw, columnId, dataView, shouldShowFieldHandler).slice(
|
||||
0,
|
||||
maxDocFieldsDisplayed
|
||||
maxEntries
|
||||
)
|
||||
: formatHit(row, dataView, shouldShowFieldHandler, maxEntries, fieldFormats);
|
||||
|
||||
|
@ -110,13 +133,13 @@ export const getRenderCellValueFn =
|
|||
<EuiDescriptionList
|
||||
type="inline"
|
||||
compressed
|
||||
className={classnames('dscDiscoverGrid__descriptionList', CELL_CLASS)}
|
||||
className={classnames('unifiedDataTable__descriptionList', CELL_CLASS)}
|
||||
>
|
||||
{pairs.map(([key, value]) => (
|
||||
<Fragment key={key}>
|
||||
<EuiDescriptionListTitle>{key}</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="dscDiscoverGrid__descriptionListDescription"
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={{ __html: value }}
|
||||
/>
|
||||
</Fragment>
|
||||
|
@ -144,7 +167,7 @@ export const getRenderCellValueFn =
|
|||
function getInnerColumns(fields: Record<string, unknown[]>, columnId: string) {
|
||||
return Object.fromEntries(
|
||||
Object.entries(fields).filter(([key]) => {
|
||||
return key.indexOf(`${columnId}.`) === 0;
|
||||
return key.startsWith(`${columnId}.`);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -178,7 +201,7 @@ function renderPopoverContent({
|
|||
}) {
|
||||
const closeButton = (
|
||||
<EuiButtonIcon
|
||||
aria-label={i18n.translate('discover.grid.closePopover', {
|
||||
aria-label={i18n.translate('unifiedDataTable.grid.closePopover', {
|
||||
defaultMessage: `Close popover`,
|
||||
})}
|
||||
data-test-subj="docTableClosePopover"
|
||||
|
@ -194,7 +217,7 @@ function renderPopoverContent({
|
|||
gutterSize="none"
|
||||
direction="column"
|
||||
justifyContent="flexEnd"
|
||||
className="dscDiscoverGrid__cellPopover"
|
||||
className="unifiedDataTable__cellPopover"
|
||||
>
|
||||
<EuiFlexItem grow={false}>
|
||||
<EuiFlexGroup justifyContent="flexEnd" gutterSize="none" responsive={false}>
|
||||
|
@ -216,7 +239,7 @@ function renderPopoverContent({
|
|||
<EuiFlexGroup gutterSize="none" direction="row" responsive={false}>
|
||||
<EuiFlexItem>
|
||||
<span
|
||||
className="dscDiscoverGrid__cellPopoverValue eui-textBreakWord"
|
||||
className="unifiedDataTable__cellPopoverValue eui-textBreakWord"
|
||||
// formatFieldValue guarantees sanitized values
|
||||
// eslint-disable-next-line react/no-danger
|
||||
dangerouslySetInnerHTML={{
|
||||
|
@ -257,7 +280,7 @@ function getTopLevelObjectPairs(
|
|||
const formatter = subField
|
||||
? dataView.getFormatterForField(subField)
|
||||
: { convert: (v: unknown, ...rest: unknown[]) => String(v) };
|
||||
const formatted = (values as unknown[])
|
||||
const formatted = values
|
||||
.map((val: unknown) =>
|
||||
formatter.convert(val, 'html', {
|
||||
field: subField,
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
|
||||
import type { Capabilities } from '@kbn/core/public';
|
||||
import { DataViewsContract } from '@kbn/data-plugin/public';
|
||||
import { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { DataViewsContract } from '@kbn/data-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
|
||||
async function popularizeField(
|
||||
dataView: DataView,
|
|
@ -6,7 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { isValidRowHeight } from './validate_row_height';
|
||||
|
||||
export interface DataGridOptionsRecord {
|
||||
|
@ -14,10 +14,13 @@ export interface DataGridOptionsRecord {
|
|||
previousConfigRowHeight: number;
|
||||
}
|
||||
|
||||
const ROW_HEIGHT_KEY = 'discover:dataGridRowHeight';
|
||||
const getRowHeightKey = (consumer: string) => `${consumer}:dataGridRowHeight`;
|
||||
|
||||
export const getStoredRowHeight = (storage: Storage): DataGridOptionsRecord | null => {
|
||||
const entry = storage.get(ROW_HEIGHT_KEY);
|
||||
export const getStoredRowHeight = (
|
||||
storage: Storage,
|
||||
consumer: string
|
||||
): DataGridOptionsRecord | null => {
|
||||
const entry = storage.get(getRowHeightKey(consumer));
|
||||
if (
|
||||
typeof entry === 'object' &&
|
||||
entry !== null &&
|
||||
|
@ -32,9 +35,10 @@ export const getStoredRowHeight = (storage: Storage): DataGridOptionsRecord | nu
|
|||
export const updateStoredRowHeight = (
|
||||
newRowHeight: number,
|
||||
configRowHeight: number,
|
||||
storage: Storage
|
||||
storage: Storage,
|
||||
consumer: string
|
||||
) => {
|
||||
storage.set(ROW_HEIGHT_KEY, {
|
||||
storage.set(getRowHeightKey(consumer), {
|
||||
previousRowHeight: newRowHeight,
|
||||
previousConfigRowHeight: configRowHeight,
|
||||
});
|
|
@ -6,9 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { discoverServiceMock } from '../__mocks__/services';
|
||||
import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils';
|
||||
import { getRowsPerPageOptions, getDefaultRowsPerPage } from './rows_per_page';
|
||||
import { getRowsPerPageOptions } from './rows_per_page';
|
||||
|
||||
const SORTED_OPTIONS = [10, 25, 50, 100, 250, 500];
|
||||
|
||||
|
@ -26,17 +24,4 @@ describe('rows per page', () => {
|
|||
expect(getRowsPerPageOptions(350)).toEqual([10, 25, 50, 100, 250, 350, 500]);
|
||||
});
|
||||
});
|
||||
|
||||
describe('getDefaultRowsPerPage', () => {
|
||||
it('should return a value from settings', () => {
|
||||
expect(getDefaultRowsPerPage(discoverServiceMock.uiSettings)).toEqual(150);
|
||||
expect(discoverServiceMock.uiSettings.get).toHaveBeenCalledWith(SAMPLE_ROWS_PER_PAGE_SETTING);
|
||||
});
|
||||
|
||||
it('should return a default value', () => {
|
||||
expect(getDefaultRowsPerPage({ ...discoverServiceMock.uiSettings, get: jest.fn() })).toEqual(
|
||||
100
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -7,9 +7,8 @@
|
|||
*/
|
||||
|
||||
import { sortBy, uniq } from 'lodash';
|
||||
import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils';
|
||||
import { DEFAULT_ROWS_PER_PAGE, ROWS_PER_PAGE_OPTIONS } from '../../common/constants';
|
||||
import { DiscoverServices } from '../build_services';
|
||||
|
||||
import { ROWS_PER_PAGE_OPTIONS } from '../constants';
|
||||
|
||||
export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] => {
|
||||
return sortBy(
|
||||
|
@ -20,7 +19,3 @@ export const getRowsPerPageOptions = (currentRowsPerPage?: number): number[] =>
|
|||
)
|
||||
);
|
||||
};
|
||||
|
||||
export const getDefaultRowsPerPage = (uiSettings: DiscoverServices['uiSettings']): number => {
|
||||
return parseInt(uiSettings.get(SAMPLE_ROWS_PER_PAGE_SETTING), 10) || DEFAULT_ROWS_PER_PAGE;
|
||||
};
|
37
packages/kbn-unified-data-table/tsconfig.json
Normal file
37
packages/kbn-unified-data-table/tsconfig.json
Normal file
|
@ -0,0 +1,37 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types"
|
||||
},
|
||||
"include": ["*.ts", "**/*.tsx", "src/**/*", "__mocks__/**/*.ts"],
|
||||
"exclude": [
|
||||
"target/**/*"
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/i18n",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/unified-doc-viewer",
|
||||
"@kbn/discover-utils",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/expressions-plugin",
|
||||
"@kbn/test-jest-helpers",
|
||||
"@kbn/i18n-react",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/field-types",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/cell-actions",
|
||||
"@kbn/utility-types",
|
||||
"@kbn/data-view-field-editor-plugin",
|
||||
"@kbn/field-formats-plugin",
|
||||
"@kbn/react-kibana-context-common",
|
||||
"@kbn/data-plugin",
|
||||
"@kbn/core",
|
||||
"@kbn/ui-actions-plugin",
|
||||
"@kbn/charts-plugin",
|
||||
"@kbn/kibana-react-plugin",
|
||||
"@kbn/monaco",
|
||||
"@kbn/code-editor",
|
||||
"@kbn/config",
|
||||
"@kbn/monaco",
|
||||
]
|
||||
}
|
|
@ -351,7 +351,7 @@ exports[`<CodeEditor /> is rendered 1`] = `
|
|||
<mockMonacoEditor
|
||||
editorDidMount={[Function]}
|
||||
editorWillMount={[Function]}
|
||||
height="100px"
|
||||
height={250}
|
||||
language="loglang"
|
||||
onChange={[Function]}
|
||||
options={
|
||||
|
|
|
@ -137,6 +137,7 @@ export const CodeEditor: React.FC<Props> = ({
|
|||
value,
|
||||
onChange,
|
||||
width,
|
||||
height = '100px',
|
||||
options,
|
||||
overrideEditorWillMount,
|
||||
editorDidMount,
|
||||
|
@ -478,7 +479,7 @@ export const CodeEditor: React.FC<Props> = ({
|
|||
onChange={onChange}
|
||||
width={isFullScreen ? '100vw' : width}
|
||||
// previously defaulted to height which defaulted to 100% but this makes it unviewable
|
||||
height={isFullScreen ? '100vh' : '100px'}
|
||||
height={isFullScreen ? '100vh' : height}
|
||||
editorWillMount={_editorWillMount}
|
||||
editorDidMount={_editorDidMount}
|
||||
options={{
|
||||
|
|
|
@ -6,12 +6,18 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const MAX_LOADED_GRID_ROWS = 10000;
|
||||
import { SAMPLE_ROWS_PER_PAGE_SETTING } from '@kbn/discover-utils';
|
||||
import { IUiSettingsClient } from '@kbn/core/public';
|
||||
|
||||
export const DEFAULT_ROWS_PER_PAGE = 100;
|
||||
export const ROWS_PER_PAGE_OPTIONS = [10, 25, 50, DEFAULT_ROWS_PER_PAGE, 250, 500];
|
||||
|
||||
export enum VIEW_MODE {
|
||||
DOCUMENT_LEVEL = 'documents',
|
||||
AGGREGATED_LEVEL = 'aggregated',
|
||||
}
|
||||
|
||||
export const DISABLE_SHARD_FAILURE_WARNING = true;
|
||||
export const getDefaultRowsPerPage = (uiSettings: IUiSettingsClient): number => {
|
||||
return parseInt(uiSettings.get(SAMPLE_ROWS_PER_PAGE_SETTING), 10) || DEFAULT_ROWS_PER_PAGE;
|
||||
};
|
||||
|
|
|
@ -18,15 +18,18 @@ import { generateFilters } from '@kbn/data-plugin/public';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { reportPerformanceMetricEvent } from '@kbn/ebt-tools';
|
||||
import { removeInterceptedWarningDuplicates } from '@kbn/search-response-warnings';
|
||||
import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import {
|
||||
DOC_TABLE_LEGACY,
|
||||
SEARCH_FIELDS_FROM_SOURCE,
|
||||
SORT_DEFAULT_ORDER_SETTING,
|
||||
} from '@kbn/discover-utils';
|
||||
import { popularizeField, useColumns } from '@kbn/unified-data-table';
|
||||
import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { ContextErrorMessage } from './components/context_error_message';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { AppState, GlobalState, isEqualFilters } from './services/context_state';
|
||||
import { useColumns } from '../../hooks/use_data_grid_columns';
|
||||
import { useContextAppState } from './hooks/use_context_app_state';
|
||||
import { useContextAppFetch } from './hooks/use_context_app_fetch';
|
||||
import { popularizeField } from '../../utils/popularize_field';
|
||||
import { ContextAppContent } from './context_app_content';
|
||||
import { SurrDocType } from './services/context';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
|
@ -68,7 +71,7 @@ export const ContextApp = ({ dataView, anchorId, referrer }: ContextAppProps) =>
|
|||
|
||||
const { columns, onAddColumn, onRemoveColumn, onSetColumns } = useColumns({
|
||||
capabilities,
|
||||
config: uiSettings,
|
||||
defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING),
|
||||
dataView,
|
||||
dataViews,
|
||||
useNewFieldsApi,
|
||||
|
|
|
@ -12,11 +12,11 @@ import { findTestSubject } from '@elastic/eui/lib/test';
|
|||
import { ActionBar } from './components/action_bar/action_bar';
|
||||
import { GetStateReturn } from './services/context_state';
|
||||
import { SortDirection } from '@kbn/data-plugin/public';
|
||||
import { UnifiedDataTable } from '@kbn/unified-data-table';
|
||||
import { ContextAppContent, ContextAppContentProps } from './context_app_content';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { dataViewMock } from '@kbn/discover-utils/src/__mocks__';
|
||||
import { discoverServiceMock } from '../../__mocks__/services';
|
||||
import { DiscoverGrid } from '../../components/discover_grid/discover_grid';
|
||||
import { DocTableWrapper } from '../../components/doc_table/doc_table_wrapper';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { buildDataTableRecord } from '@kbn/discover-utils';
|
||||
|
@ -103,6 +103,6 @@ describe('ContextAppContent test', () => {
|
|||
|
||||
it('should render discover grid correctly', async () => {
|
||||
const component = await mountComponent({ isLegacy: false });
|
||||
expect(component.find(DiscoverGrid).length).toBe(1);
|
||||
expect(component.find(UnifiedDataTable).length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -18,17 +18,25 @@ import {
|
|||
type SearchResponseInterceptedWarning,
|
||||
SearchResponseWarnings,
|
||||
} from '@kbn/search-response-warnings';
|
||||
import { CONTEXT_STEP_SETTING, DOC_HIDE_TIME_COLUMN_SETTING } from '@kbn/discover-utils';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import {
|
||||
CONTEXT_STEP_SETTING,
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
ROW_HEIGHT_OPTION,
|
||||
SHOW_MULTIFIELDS,
|
||||
} from '@kbn/discover-utils';
|
||||
import { DataLoadingState, UnifiedDataTable } from '@kbn/unified-data-table';
|
||||
import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { getDefaultRowsPerPage } from '../../../common/constants';
|
||||
import { LoadingStatus } from './services/context_query_state';
|
||||
import { ActionBar } from './components/action_bar/action_bar';
|
||||
import { DataLoadingState, DiscoverGrid } from '../../components/discover_grid/discover_grid';
|
||||
import { AppState } from './services/context_state';
|
||||
import { SurrDocType } from './services/context';
|
||||
import { MAX_CONTEXT_SIZE, MIN_CONTEXT_SIZE } from './services/constants';
|
||||
import { DocTableContext } from '../../components/doc_table/doc_table_context';
|
||||
import { useDiscoverServices } from '../../hooks/use_discover_services';
|
||||
import { DiscoverGridFlyout } from '../../components/discover_grid/discover_grid_flyout';
|
||||
import { DiscoverGridFlyout } from '../../components/discover_grid_flyout';
|
||||
import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../../components/discover_tour';
|
||||
|
||||
export interface ContextAppContentProps {
|
||||
columns: string[];
|
||||
|
@ -57,7 +65,7 @@ export function clamp(value: number) {
|
|||
return Math.max(Math.min(MAX_CONTEXT_SIZE, value), MIN_CONTEXT_SIZE);
|
||||
}
|
||||
|
||||
const DiscoverGridMemoized = React.memo(DiscoverGrid);
|
||||
const DiscoverGridMemoized = React.memo(UnifiedDataTable);
|
||||
const DocTableContextMemoized = React.memo(DocTableContext);
|
||||
const ActionBarMemoized = React.memo(ActionBar);
|
||||
|
||||
|
@ -121,6 +129,24 @@ export function ContextAppContent({
|
|||
return [[dataView.timeFieldName!, SortDirection.desc]];
|
||||
}, [dataView]);
|
||||
|
||||
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}
|
||||
onFilter={addFilter}
|
||||
onRemoveColumn={onRemoveColumn}
|
||||
onAddColumn={onAddColumn}
|
||||
onClose={() => setExpandedDoc(undefined)}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
/>
|
||||
),
|
||||
[addFilter, dataView, onAddColumn, onRemoveColumn]
|
||||
);
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
{!!interceptedWarnings?.length && (
|
||||
|
@ -174,14 +200,17 @@ export function ContextAppContent({
|
|||
showTimeCol={showTimeCol}
|
||||
useNewFieldsApi={useNewFieldsApi}
|
||||
isPaginationEnabled={false}
|
||||
rowsPerPageState={getDefaultRowsPerPage(services.uiSettings)}
|
||||
controlColumnIds={controlColumnIds}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
onFilter={addFilter}
|
||||
onAddColumn={onAddColumn}
|
||||
onRemoveColumn={onRemoveColumn}
|
||||
onSetColumns={onSetColumns}
|
||||
DocumentView={DiscoverGridFlyout}
|
||||
configRowHeight={services.uiSettings.get(ROW_HEIGHT_OPTION)}
|
||||
showMultiFields={services.uiSettings.get(SHOW_MULTIFIELDS)}
|
||||
maxDocFieldsDisplayed={services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)}
|
||||
renderDocumentView={renderDocumentView}
|
||||
services={services}
|
||||
componentsTourSteps={{ expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument }}
|
||||
/>
|
||||
</CellActionsProvider>
|
||||
</div>
|
||||
|
|
|
@ -21,29 +21,36 @@ import { SortOrder } from '@kbn/saved-search-plugin/public';
|
|||
import { CellActionsProvider } from '@kbn/cell-actions';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { SearchResponseWarnings } from '@kbn/search-response-warnings';
|
||||
import { DataLoadingState, UnifiedDataTable, useColumns } from '@kbn/unified-data-table';
|
||||
import {
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
DOC_TABLE_LEGACY,
|
||||
HIDE_ANNOUNCEMENTS,
|
||||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
ROW_HEIGHT_OPTION,
|
||||
SAMPLE_SIZE_SETTING,
|
||||
SEARCH_FIELDS_FROM_SOURCE,
|
||||
SHOW_MULTIFIELDS,
|
||||
SORT_DEFAULT_ORDER_SETTING,
|
||||
} from '@kbn/discover-utils';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { getDefaultRowsPerPage } from '../../../../../common/constants';
|
||||
import { useInternalStateSelector } from '../../services/discover_internal_state_container';
|
||||
import { useAppStateSelector } from '../../services/discover_app_state_container';
|
||||
import { useDiscoverServices } from '../../../../hooks/use_discover_services';
|
||||
import { DataLoadingState, DiscoverGrid } from '../../../../components/discover_grid/discover_grid';
|
||||
import { FetchStatus } from '../../../types';
|
||||
import { useColumns } from '../../../../hooks/use_data_grid_columns';
|
||||
import { RecordRawType } from '../../services/discover_data_state_container';
|
||||
import { DiscoverStateContainer } from '../../services/discover_state';
|
||||
import { useDataState } from '../../hooks/use_data_state';
|
||||
import { DocTableInfinite } from '../../../../components/doc_table/doc_table_infinite';
|
||||
import { DocumentExplorerCallout } from '../document_explorer_callout';
|
||||
import { DocumentExplorerUpdateCallout } from '../document_explorer_callout/document_explorer_update_callout';
|
||||
import { DiscoverTourProvider } from '../../../../components/discover_tour';
|
||||
import {
|
||||
DISCOVER_TOUR_STEP_ANCHOR_IDS,
|
||||
DiscoverTourProvider,
|
||||
} from '../../../../components/discover_tour';
|
||||
import { getRawRecordType } from '../../utils/get_raw_record_type';
|
||||
import { DiscoverGridFlyout } from '../../../../components/discover_grid/discover_grid_flyout';
|
||||
import { DiscoverGridFlyout } from '../../../../components/discover_grid_flyout';
|
||||
import { useSavedSearchInitial } from '../../services/discover_state_provider';
|
||||
import { useFetchMoreRecords } from './use_fetch_more_records';
|
||||
|
||||
|
@ -56,7 +63,7 @@ const progressStyle = css`
|
|||
`;
|
||||
|
||||
const DocTableInfiniteMemoized = React.memo(DocTableInfinite);
|
||||
const DiscoverGridMemoized = React.memo(DiscoverGrid);
|
||||
const DataGridMemoized = React.memo(UnifiedDataTable);
|
||||
|
||||
// export needs for testing
|
||||
export const onResize = (
|
||||
|
@ -147,7 +154,7 @@ function DiscoverDocumentsComponent({
|
|||
onSetColumns,
|
||||
} = useColumns({
|
||||
capabilities,
|
||||
config: uiSettings,
|
||||
defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING),
|
||||
dataView,
|
||||
dataViews,
|
||||
setAppState: stateContainer.appState.update,
|
||||
|
@ -191,6 +198,26 @@ function DiscoverDocumentsComponent({
|
|||
[isTextBasedQuery, columns, uiSettings, dataView.timeFieldName]
|
||||
);
|
||||
|
||||
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]
|
||||
);
|
||||
|
||||
if (isDataViewLoading || (isEmptyDataResult && isDataLoading)) {
|
||||
return (
|
||||
<div className="dscDocuments__loading">
|
||||
|
@ -217,7 +244,7 @@ function DiscoverDocumentsComponent({
|
|||
data-test-subj="dscInterceptedWarningsCallout"
|
||||
/>
|
||||
)}
|
||||
{isLegacy && rows && rows.length && (
|
||||
{isLegacy && rows && rows.length > 0 && (
|
||||
<>
|
||||
{!hideAnnouncements && <DocumentExplorerCallout />}
|
||||
<DocTableInfiniteMemoized
|
||||
|
@ -246,11 +273,11 @@ function DiscoverDocumentsComponent({
|
|||
<DocumentExplorerUpdateCallout />
|
||||
</DiscoverTourProvider>
|
||||
)}
|
||||
<div className="dscDiscoverGrid">
|
||||
<div className="unifiedDataTable">
|
||||
<CellActionsProvider
|
||||
getTriggerCompatibleActions={uiActions.getTriggerCompatibleActions}
|
||||
>
|
||||
<DiscoverGridMemoized
|
||||
<DataGridMemoized
|
||||
ariaLabelledBy="documentsAriaLabel"
|
||||
columns={currentColumns}
|
||||
expandedDoc={expandedDoc}
|
||||
|
@ -270,9 +297,7 @@ function DiscoverDocumentsComponent({
|
|||
setExpandedDoc={setExpandedDoc}
|
||||
showTimeCol={showTimeCol}
|
||||
settings={grid}
|
||||
onAddColumn={onAddColumn}
|
||||
onFilter={onAddFilter as DocViewFilterFn}
|
||||
onRemoveColumn={onRemoveColumn}
|
||||
onSetColumns={onSetColumns}
|
||||
onSort={!isTextBasedQuery ? onSort : undefined}
|
||||
onResize={onResizeDataGrid}
|
||||
|
@ -281,15 +306,17 @@ function DiscoverDocumentsComponent({
|
|||
onUpdateRowHeight={onUpdateRowHeight}
|
||||
isSortEnabled={isTextBasedQuery ? Boolean(currentColumns.length) : true}
|
||||
isPlainRecord={isTextBasedQuery}
|
||||
query={query}
|
||||
rowsPerPageState={rowsPerPage}
|
||||
rowsPerPageState={rowsPerPage ?? getDefaultRowsPerPage(services.uiSettings)}
|
||||
onUpdateRowsPerPage={onUpdateRowsPerPage}
|
||||
onFieldEdited={onFieldEdited}
|
||||
savedSearchId={savedSearch.id}
|
||||
DocumentView={DiscoverGridFlyout}
|
||||
configRowHeight={uiSettings.get(ROW_HEIGHT_OPTION)}
|
||||
showMultiFields={uiSettings.get(SHOW_MULTIFIELDS)}
|
||||
maxDocFieldsDisplayed={uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)}
|
||||
renderDocumentView={renderDocumentView}
|
||||
services={services}
|
||||
totalHits={totalHits}
|
||||
onFetchMoreRecords={onFetchMoreRecords}
|
||||
componentsTourSteps={{ expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument }}
|
||||
/>
|
||||
</CellActionsProvider>
|
||||
</div>
|
||||
|
|
|
@ -23,8 +23,13 @@ import classNames from 'classnames';
|
|||
import { generateFilters } from '@kbn/data-plugin/public';
|
||||
import { useDragDropContext } from '@kbn/dom-drag-drop';
|
||||
import { DataViewField, DataViewType } from '@kbn/data-views-plugin/public';
|
||||
import { SEARCH_FIELDS_FROM_SOURCE, SHOW_FIELD_STATISTICS } from '@kbn/discover-utils';
|
||||
import type { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import {
|
||||
SEARCH_FIELDS_FROM_SOURCE,
|
||||
SHOW_FIELD_STATISTICS,
|
||||
SORT_DEFAULT_ORDER_SETTING,
|
||||
} from '@kbn/discover-utils';
|
||||
import { popularizeField, useColumns } from '@kbn/unified-data-table';
|
||||
import { DocViewFilterFn } from '@kbn/unified-doc-viewer/types';
|
||||
import { useSavedSearchInitial } from '../../services/discover_state_provider';
|
||||
import { DiscoverStateContainer } from '../../services/discover_state';
|
||||
import { VIEW_MODE } from '../../../../../common/constants';
|
||||
|
@ -35,12 +40,10 @@ import { useDiscoverServices } from '../../../../hooks/use_discover_services';
|
|||
import { DiscoverNoResults } from '../no_results';
|
||||
import { LoadingSpinner } from '../loading_spinner/loading_spinner';
|
||||
import { DiscoverSidebarResponsive } from '../sidebar';
|
||||
import { popularizeField } from '../../../../utils/popularize_field';
|
||||
import { DiscoverTopNav } from '../top_nav/discover_topnav';
|
||||
import { getResultState } from '../../utils/get_result_state';
|
||||
import { DiscoverUninitialized } from '../uninitialized/uninitialized';
|
||||
import { DataMainMsg, RecordRawType } from '../../services/discover_data_state_container';
|
||||
import { useColumns } from '../../../../hooks/use_data_grid_columns';
|
||||
import { FetchStatus } from '../../../types';
|
||||
import { useDataState } from '../../hooks/use_data_state';
|
||||
import { getRawRecordType } from '../../utils/get_raw_record_type';
|
||||
|
@ -127,7 +130,7 @@ export function DiscoverLayout({ stateContainer }: DiscoverLayoutProps) {
|
|||
onRemoveColumn,
|
||||
} = useColumns({
|
||||
capabilities,
|
||||
config: uiSettings,
|
||||
defaultOrder: uiSettings.get(SORT_DEFAULT_ORDER_SETTING),
|
||||
dataView,
|
||||
dataViews,
|
||||
setAppState: stateContainer.appState.update,
|
||||
|
|
|
@ -23,12 +23,12 @@ import { SavedSearch, VIEW_MODE } from '@kbn/saved-search-plugin/public';
|
|||
import { IKbnUrlStateStorage, ISyncStateRef, syncState } from '@kbn/kibana-utils-plugin/public';
|
||||
import { isEqual } from 'lodash';
|
||||
import { connectToQueryState, syncGlobalQueryStateWithUrl } from '@kbn/data-plugin/public';
|
||||
import type { UnifiedDataTableSettings } from '@kbn/unified-data-table';
|
||||
import type { DiscoverServices } from '../../../build_services';
|
||||
import { addLog } from '../../../utils/add_log';
|
||||
import { cleanupUrlState } from '../utils/cleanup_url_state';
|
||||
import { getStateDefaults } from '../utils/get_state_defaults';
|
||||
import { handleSourceColumnState } from '../../../utils/state_helpers';
|
||||
import type { DiscoverGridSettings } from '../../../components/discover_grid/types';
|
||||
|
||||
export const APP_STATE_URL_KEY = '_a';
|
||||
export interface DiscoverAppStateContainer extends ReduxLikeStateContainer<DiscoverAppState> {
|
||||
|
@ -87,7 +87,7 @@ export interface DiscoverAppState {
|
|||
/**
|
||||
* Data Grid related state
|
||||
*/
|
||||
grid?: DiscoverGridSettings;
|
||||
grid?: UnifiedDataTableSettings;
|
||||
/**
|
||||
* Hide chart
|
||||
*/
|
||||
|
|
|
@ -12,7 +12,7 @@ import { isCompleteResponse, ISearchSource } from '@kbn/data-plugin/public';
|
|||
import { SAMPLE_SIZE_SETTING, buildDataTableRecordList } from '@kbn/discover-utils';
|
||||
import type { EsHitRecord } from '@kbn/discover-utils/types';
|
||||
import { getSearchResponseInterceptedWarnings } from '@kbn/search-response-warnings';
|
||||
import type { RecordsFetchResponse } from '../../../types';
|
||||
import type { RecordsFetchResponse } from '../../types';
|
||||
import { DISABLE_SHARD_FAILURE_WARNING } from '../../../../common/constants';
|
||||
import { FetchDeps } from './fetch_all';
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import type { Datatable } from '@kbn/expressions-plugin/public';
|
|||
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { textBasedQueryStateToAstWithValidation } from '@kbn/data-plugin/common';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { RecordsFetchResponse } from '../../../types';
|
||||
import type { RecordsFetchResponse } from '../../types';
|
||||
|
||||
interface TextBasedErrorResponse {
|
||||
error: {
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { DatatableColumn } from '@kbn/expressions-plugin/common';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings';
|
||||
|
||||
export enum FetchStatus {
|
||||
UNINITIALIZED = 'uninitialized',
|
||||
LOADING = 'loading',
|
||||
|
@ -16,3 +20,10 @@ export enum FetchStatus {
|
|||
}
|
||||
|
||||
export type DiscoverDisplayMode = 'embedded' | 'standalone';
|
||||
|
||||
export interface RecordsFetchResponse {
|
||||
records: DataTableRecord[];
|
||||
textBasedQueryColumns?: DatatableColumn[];
|
||||
textBasedHeaderWarning?: string;
|
||||
interceptedWarnings?: SearchResponseInterceptedWarning[];
|
||||
}
|
||||
|
|
|
@ -1,159 +0,0 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
const mockCopyToClipboard = jest.fn((value) => true);
|
||||
jest.mock('@elastic/eui', () => {
|
||||
const original = jest.requireActual('@elastic/eui');
|
||||
return {
|
||||
...original,
|
||||
copyToClipboard: (value: string) => mockCopyToClipboard(value),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('../../hooks/use_discover_services', () => {
|
||||
const services = {
|
||||
toastNotifications: {
|
||||
addInfo: jest.fn(),
|
||||
},
|
||||
};
|
||||
const originalModule = jest.requireActual('../../hooks/use_discover_services');
|
||||
return {
|
||||
...originalModule,
|
||||
useDiscoverServices: () => services,
|
||||
};
|
||||
});
|
||||
|
||||
import React from 'react';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import { findTestSubject } from '@elastic/eui/lib/test';
|
||||
import { FilterInBtn, FilterOutBtn, buildCellActions, CopyBtn } from './discover_grid_cell_actions';
|
||||
import { DiscoverGridContext } from './discover_grid_context';
|
||||
import { EuiButton } from '@elastic/eui';
|
||||
import { discoverGridContextMock } from '../../__mocks__/grid_context';
|
||||
import { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
|
||||
describe('Discover cell actions ', function () {
|
||||
it('should not show cell actions for unfilterable fields', async () => {
|
||||
expect(buildCellActions({ name: 'foo', filterable: false } as DataViewField)).toEqual([
|
||||
CopyBtn,
|
||||
]);
|
||||
});
|
||||
|
||||
it('should show filter actions for filterable fields', async () => {
|
||||
expect(buildCellActions({ name: 'foo', filterable: true } as DataViewField, jest.fn())).toEqual(
|
||||
[FilterInBtn, FilterOutBtn, CopyBtn]
|
||||
);
|
||||
});
|
||||
|
||||
it('should show Copy action for _source field', async () => {
|
||||
expect(
|
||||
buildCellActions({ name: '_source', type: '_source', filterable: false } as DataViewField)
|
||||
).toEqual([CopyBtn]);
|
||||
});
|
||||
|
||||
it('triggers filter function when FilterInBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={discoverGridContextMock}>
|
||||
<FilterInBtn
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith(
|
||||
discoverGridContextMock.dataView.fields.getByName('extension'),
|
||||
'jpg',
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterInBtn is clicked for a non-provided value', async () => {
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={discoverGridContextMock}>
|
||||
<FilterInBtn
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={0}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith(
|
||||
discoverGridContextMock.dataView.fields.getByName('extension'),
|
||||
undefined,
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterInBtn is clicked for an empty string value', async () => {
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={discoverGridContextMock}>
|
||||
<FilterInBtn
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={4}
|
||||
colIndex={1}
|
||||
columnId="message"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterForButton');
|
||||
await button.simulate('click');
|
||||
expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith(
|
||||
discoverGridContextMock.dataView.fields.getByName('message'),
|
||||
'',
|
||||
'+'
|
||||
);
|
||||
});
|
||||
it('triggers filter function when FilterOutBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={discoverGridContextMock}>
|
||||
<FilterOutBtn
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'filterOutButton');
|
||||
await button.simulate('click');
|
||||
expect(discoverGridContextMock.onFilter).toHaveBeenCalledWith(
|
||||
discoverGridContextMock.dataView.fields.getByName('extension'),
|
||||
'jpg',
|
||||
'-'
|
||||
);
|
||||
});
|
||||
it('triggers clipboard copy when CopyBtn is clicked', async () => {
|
||||
const component = mountWithIntl(
|
||||
<DiscoverGridContext.Provider value={discoverGridContextMock}>
|
||||
<CopyBtn
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Component={(props: any) => <EuiButton {...props} />}
|
||||
rowIndex={1}
|
||||
colIndex={1}
|
||||
columnId="extension"
|
||||
isExpanded={false}
|
||||
/>
|
||||
</DiscoverGridContext.Provider>
|
||||
);
|
||||
const button = findTestSubject(component, 'copyClipboardButton');
|
||||
await button.simulate('click');
|
||||
expect(mockCopyToClipboard).toHaveBeenCalledWith('jpg');
|
||||
});
|
||||
});
|
|
@ -45,7 +45,7 @@ export interface DiscoverGridFlyoutProps {
|
|||
onClose: () => void;
|
||||
onFilter?: DocViewFilterFn;
|
||||
onRemoveColumn: (column: string) => void;
|
||||
setExpandedDoc: (doc: DataTableRecord) => void;
|
||||
setExpandedDoc: (doc?: DataTableRecord) => void;
|
||||
}
|
||||
|
||||
function getIndexByDocId(hits: DataTableRecord[], id: string) {
|
||||
|
@ -120,7 +120,7 @@ export function DiscoverGridFlyout({
|
|||
<EuiFlyoutHeader hasBorder>
|
||||
<EuiTitle
|
||||
size="s"
|
||||
className="dscTable__flyoutHeader"
|
||||
className="unifiedDataTable__flyoutHeader"
|
||||
data-test-subj="docTableRowDetailsTitle"
|
||||
>
|
||||
<h2>
|
||||
|
@ -216,7 +216,7 @@ export function DiscoverGridFlyout({
|
|||
pageCount={pageCount}
|
||||
activePage={activePage}
|
||||
onPageClick={setPage}
|
||||
className="dscTable__flyoutDocumentNavigation"
|
||||
className="unifiedDataTable__flyoutDocumentNavigation"
|
||||
compressed
|
||||
data-test-subj="dscDocNavigation"
|
||||
/>
|
||||
|
@ -255,3 +255,6 @@ export function DiscoverGridFlyout({
|
|||
</EuiPortal>
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export default DiscoverGridFlyout;
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { withSuspense } from '@kbn/shared-ux-utility';
|
||||
import { lazy } from 'react';
|
||||
export type { DiscoverGridFlyoutProps } from './discover_grid_flyout';
|
||||
|
||||
export const DiscoverGridFlyout = withSuspense(lazy(() => import('./discover_grid_flyout')));
|
|
@ -19,7 +19,7 @@ import {
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { euiLightVars } from '@kbn/ui-theme';
|
||||
import { getRowsPerPageOptions } from '../../../../utils/rows_per_page';
|
||||
import { getRowsPerPageOptions } from '@kbn/unified-data-table';
|
||||
|
||||
export const MAX_ROWS_PER_PAGE_OPTION = 100;
|
||||
|
||||
|
|
|
@ -59,16 +59,20 @@ import {
|
|||
SORT_DEFAULT_ORDER_SETTING,
|
||||
buildDataTableRecord,
|
||||
} from '@kbn/discover-utils';
|
||||
import { VIEW_MODE, DISABLE_SHARD_FAILURE_WARNING } from '../../common/constants';
|
||||
import type { UnifiedDataTableProps } from '@kbn/unified-data-table';
|
||||
import type { UnifiedDataTableSettings } from '@kbn/unified-data-table';
|
||||
import { columnActions } from '@kbn/unified-data-table';
|
||||
import {
|
||||
VIEW_MODE,
|
||||
DISABLE_SHARD_FAILURE_WARNING,
|
||||
getDefaultRowsPerPage,
|
||||
} from '../../common/constants';
|
||||
import type { ISearchEmbeddable, SearchInput, SearchOutput } from './types';
|
||||
import type { DiscoverServices } from '../build_services';
|
||||
import { getSortForEmbeddable, SortPair } from '../utils/sorting';
|
||||
import { SEARCH_EMBEDDABLE_TYPE, SEARCH_EMBEDDABLE_CELL_ACTIONS_TRIGGER_ID } from './constants';
|
||||
import { SavedSearchEmbeddableComponent } from './saved_search_embeddable_component';
|
||||
import * as columnActions from '../components/doc_table/actions/columns';
|
||||
import { handleSourceColumnState } from '../utils/state_helpers';
|
||||
import type { DiscoverGridProps } from '../components/discover_grid/discover_grid';
|
||||
import type { DiscoverGridSettings } from '../components/discover_grid/types';
|
||||
import type { DocTableProps } from '../components/doc_table/doc_table_wrapper';
|
||||
import { updateSearchSource } from './utils/update_search_source';
|
||||
import { FieldStatisticsTable } from '../application/main/components/field_stats_table';
|
||||
|
@ -78,11 +82,11 @@ import { getValidViewMode } from '../application/main/utils/get_valid_view_mode'
|
|||
import { ADHOC_DATA_VIEW_RENDER_EVENT } from '../constants';
|
||||
import { getDiscoverLocatorParams } from './get_discover_locator_params';
|
||||
|
||||
export type SearchProps = Partial<DiscoverGridProps> &
|
||||
export type SearchProps = Partial<UnifiedDataTableProps> &
|
||||
Partial<DocTableProps> & {
|
||||
savedSearchId?: string;
|
||||
filters?: Filter[];
|
||||
settings?: DiscoverGridSettings;
|
||||
settings?: UnifiedDataTableSettings;
|
||||
description?: string;
|
||||
sharedItemTitle?: string;
|
||||
inspectorAdapters?: Adapters;
|
||||
|
@ -585,7 +589,10 @@ export class SavedSearchEmbeddable
|
|||
searchProps.sharedItemTitle = this.panelTitle;
|
||||
searchProps.searchTitle = this.panelTitle;
|
||||
searchProps.rowHeightState = this.input.rowHeight || savedSearch.rowHeight;
|
||||
searchProps.rowsPerPageState = this.input.rowsPerPage || savedSearch.rowsPerPage;
|
||||
searchProps.rowsPerPageState =
|
||||
this.input.rowsPerPage ||
|
||||
savedSearch.rowsPerPage ||
|
||||
getDefaultRowsPerPage(this.services.uiSettings);
|
||||
searchProps.filters = savedSearch.searchSource.getField('filter') as Filter[];
|
||||
searchProps.savedSearchId = savedSearch.id;
|
||||
|
||||
|
|
|
@ -8,11 +8,8 @@
|
|||
|
||||
import React from 'react';
|
||||
import { AggregateQuery, Query } from '@kbn/es-query';
|
||||
import {
|
||||
DiscoverGridEmbeddable,
|
||||
DiscoverGridEmbeddableProps,
|
||||
DataLoadingState,
|
||||
} from './saved_search_grid';
|
||||
import { DataLoadingState } from '@kbn/unified-data-table';
|
||||
import { DiscoverGridEmbeddable, DiscoverGridEmbeddableProps } from './saved_search_grid';
|
||||
import { DiscoverDocTableEmbeddable } from '../components/doc_table/create_doc_table_embeddable';
|
||||
import { DocTableEmbeddableProps } from '../components/doc_table/doc_table_embeddable';
|
||||
import { isTextBasedQuery } from '../application/main/utils/is_text_based_query';
|
||||
|
@ -47,7 +44,7 @@ export function SavedSearchEmbeddableComponent({
|
|||
loadingState={searchProps.isLoading ? DataLoadingState.loading : DataLoadingState.loaded}
|
||||
showFullScreenButton={false}
|
||||
query={query}
|
||||
className="dscDiscoverGrid"
|
||||
className="unifiedDataTable"
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
@ -5,43 +5,80 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import React, { memo, useState } from 'react';
|
||||
import React, { memo, useCallback, useState } from 'react';
|
||||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { AggregateQuery, Query } from '@kbn/es-query';
|
||||
import type { SearchResponseInterceptedWarning } from '@kbn/search-response-warnings';
|
||||
import {
|
||||
DiscoverGrid,
|
||||
DiscoverGridProps,
|
||||
DataLoadingState as DiscoverDataLoadingState,
|
||||
} from '../components/discover_grid/discover_grid';
|
||||
DataLoadingState as DiscoverGridLoadingState,
|
||||
UnifiedDataTable,
|
||||
} from '@kbn/unified-data-table';
|
||||
import type { UnifiedDataTableProps } from '@kbn/unified-data-table';
|
||||
import './saved_search_grid.scss';
|
||||
import { DiscoverGridFlyout } from '../components/discover_grid/discover_grid_flyout';
|
||||
import { MAX_DOC_FIELDS_DISPLAYED, ROW_HEIGHT_OPTION, SHOW_MULTIFIELDS } from '@kbn/discover-utils';
|
||||
import { DiscoverGridFlyout } from '../components/discover_grid_flyout';
|
||||
import { SavedSearchEmbeddableBase } from './saved_search_embeddable_base';
|
||||
export { DataLoadingState } from '../components/discover_grid/discover_grid';
|
||||
import { DISCOVER_TOUR_STEP_ANCHOR_IDS } from '../components/discover_tour';
|
||||
|
||||
export interface DiscoverGridEmbeddableProps extends DiscoverGridProps {
|
||||
export interface DiscoverGridEmbeddableProps extends UnifiedDataTableProps {
|
||||
totalHitCount?: number;
|
||||
query?: AggregateQuery | Query;
|
||||
interceptedWarnings?: SearchResponseInterceptedWarning[];
|
||||
onAddColumn: (column: string) => void;
|
||||
onRemoveColumn: (column: string) => void;
|
||||
savedSearchId?: string;
|
||||
}
|
||||
|
||||
export const DiscoverGridMemoized = memo(DiscoverGrid);
|
||||
export const DataGridMemoized = memo(UnifiedDataTable);
|
||||
|
||||
export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
|
||||
const { interceptedWarnings, ...gridProps } = props;
|
||||
const [expandedDoc, setExpandedDoc] = useState<DataTableRecord | undefined>(undefined);
|
||||
|
||||
const renderDocumentView = useCallback(
|
||||
(hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => (
|
||||
<DiscoverGridFlyout
|
||||
dataView={props.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={props.savedSearchId}
|
||||
onFilter={props.onFilter}
|
||||
onRemoveColumn={props.onRemoveColumn}
|
||||
onAddColumn={props.onAddColumn}
|
||||
onClose={() => setExpandedDoc(undefined)}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
query={props.query}
|
||||
/>
|
||||
),
|
||||
[
|
||||
props.dataView,
|
||||
props.onAddColumn,
|
||||
props.onFilter,
|
||||
props.onRemoveColumn,
|
||||
props.query,
|
||||
props.savedSearchId,
|
||||
]
|
||||
);
|
||||
|
||||
return (
|
||||
<SavedSearchEmbeddableBase
|
||||
totalHitCount={props.totalHitCount}
|
||||
isLoading={props.loadingState === DiscoverDataLoadingState.loading}
|
||||
isLoading={props.loadingState === DiscoverGridLoadingState.loading}
|
||||
dataTestSubj="embeddedSavedSearchDocTable"
|
||||
interceptedWarnings={props.interceptedWarnings}
|
||||
>
|
||||
<DiscoverGridMemoized
|
||||
<DataGridMemoized
|
||||
{...gridProps}
|
||||
totalHits={props.totalHitCount}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
expandedDoc={expandedDoc}
|
||||
DocumentView={DiscoverGridFlyout}
|
||||
configRowHeight={props.services.uiSettings.get(ROW_HEIGHT_OPTION)}
|
||||
showMultiFields={props.services.uiSettings.get(SHOW_MULTIFIELDS)}
|
||||
maxDocFieldsDisplayed={props.services.uiSettings.get(MAX_DOC_FIELDS_DISPLAYED)}
|
||||
renderDocumentView={renderDocumentView}
|
||||
componentsTourSteps={{ expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument }}
|
||||
/>
|
||||
</SavedSearchEmbeddableBase>
|
||||
);
|
||||
|
|
|
@ -1,107 +0,0 @@
|
|||
/*
|
||||
* 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 React, { ReactNode } from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { DiscoverServices } from '../build_services';
|
||||
import { LocalStorageMock } from '../__mocks__/local_storage_mock';
|
||||
import { uiSettingsMock } from '../__mocks__/ui_settings';
|
||||
import { useRowHeightsOptions } from './use_row_heights_options';
|
||||
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
|
||||
|
||||
const CONFIG_ROW_HEIGHT = 3;
|
||||
|
||||
const getWrapper = (services: DiscoverServices) => {
|
||||
return ({ children }: { children: ReactNode }) => (
|
||||
<KibanaContextProvider services={services}>{children}</KibanaContextProvider>
|
||||
);
|
||||
};
|
||||
|
||||
describe('useRowHeightsOptions', () => {
|
||||
test('should apply rowHeight from savedSearch', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
return useRowHeightsOptions({
|
||||
rowHeightState: 2,
|
||||
});
|
||||
},
|
||||
{
|
||||
wrapper: getWrapper({
|
||||
uiSettings: uiSettingsMock,
|
||||
storage: new LocalStorageMock({}) as unknown as Storage,
|
||||
} as DiscoverServices),
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({ lineCount: 2 });
|
||||
});
|
||||
|
||||
test('should apply rowHeight from local storage', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
return useRowHeightsOptions({});
|
||||
},
|
||||
{
|
||||
wrapper: getWrapper({
|
||||
uiSettings: uiSettingsMock,
|
||||
storage: new LocalStorageMock({
|
||||
['discover:dataGridRowHeight']: {
|
||||
previousRowHeight: 5,
|
||||
previousConfigRowHeight: 3,
|
||||
},
|
||||
}) as unknown as Storage,
|
||||
} as DiscoverServices),
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({ lineCount: 5 });
|
||||
});
|
||||
|
||||
test('should apply rowHeight from uiSettings', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
return useRowHeightsOptions({});
|
||||
},
|
||||
{
|
||||
wrapper: getWrapper({
|
||||
uiSettings: uiSettingsMock,
|
||||
storage: new LocalStorageMock({}) as unknown as Storage,
|
||||
} as unknown as DiscoverServices),
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({
|
||||
lineCount: CONFIG_ROW_HEIGHT,
|
||||
});
|
||||
});
|
||||
|
||||
test('should apply rowHeight from uiSettings instead of local storage value, since uiSettings has been changed', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
return useRowHeightsOptions({});
|
||||
},
|
||||
{
|
||||
wrapper: getWrapper({
|
||||
uiSettings: uiSettingsMock,
|
||||
storage: new LocalStorageMock({
|
||||
['discover:dataGridRowHeight']: {
|
||||
previousRowHeight: 4,
|
||||
// different from uiSettings (config), now user changed it to 3, but prev was 4
|
||||
previousConfigRowHeight: 4,
|
||||
},
|
||||
}) as unknown as Storage,
|
||||
} as unknown as DiscoverServices),
|
||||
}
|
||||
);
|
||||
|
||||
expect(result.current.defaultHeight).toEqual({
|
||||
lineCount: CONFIG_ROW_HEIGHT,
|
||||
});
|
||||
});
|
||||
});
|
|
@ -63,7 +63,6 @@
|
|||
"@kbn/core-application-browser",
|
||||
"@kbn/core-saved-objects-server",
|
||||
"@kbn/discover-utils",
|
||||
"@kbn/field-types",
|
||||
"@kbn/search-response-warnings",
|
||||
"@kbn/content-management-plugin",
|
||||
"@kbn/unified-doc-viewer",
|
||||
|
@ -71,6 +70,7 @@
|
|||
"@kbn/serverless",
|
||||
"@kbn/react-kibana-mount",
|
||||
"@kbn/react-kibana-context-render",
|
||||
"@kbn/unified-data-table",
|
||||
"@kbn/no-data-page-plugin"
|
||||
],
|
||||
"exclude": [
|
||||
|
|
|
@ -16,8 +16,7 @@ import type { DataView } from '@kbn/data-views-plugin/public';
|
|||
import type { DataTableRecord } from '@kbn/discover-utils/types';
|
||||
import { ElasticRequestState } from '@kbn/unified-doc-viewer';
|
||||
import { DOC_TABLE_LEGACY, SEARCH_FIELDS_FROM_SOURCE } from '@kbn/discover-utils';
|
||||
import { useEsDocSearch } from '../../hooks';
|
||||
import { useUnifiedDocViewerServices } from '../../hooks';
|
||||
import { useEsDocSearch, useUnifiedDocViewerServices } from '../../hooks';
|
||||
import { getHeight } from './get_height';
|
||||
import { JSONCodeEditorCommonMemoized } from '../json_code_editor';
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import expect from '@kbn/expect';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
const FOOTER_SELECTOR = 'discoverTableFooter';
|
||||
const FOOTER_SELECTOR = 'unifiedDataTableFooter';
|
||||
const LOAD_MORE_SELECTOR = 'dscGridSampleSizeFetchMoreLink';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
|
|
|
@ -52,18 +52,18 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
it('should show footer only for the last page', async () => {
|
||||
// footer is not shown
|
||||
await testSubjects.missingOrFail('discoverTableFooter');
|
||||
await testSubjects.missingOrFail('unifiedDataTableFooter');
|
||||
// go to next page
|
||||
await testSubjects.click('pagination-button-next');
|
||||
// footer is not shown yet
|
||||
await retry.try(async function () {
|
||||
await testSubjects.missingOrFail('discoverTableFooter');
|
||||
await testSubjects.missingOrFail('unifiedDataTableFooter');
|
||||
});
|
||||
// go to the last page
|
||||
await testSubjects.click('pagination-button-4');
|
||||
// footer is shown now
|
||||
await retry.try(async function () {
|
||||
await testSubjects.existOrFail('discoverTableFooter');
|
||||
await testSubjects.existOrFail('unifiedDataTableFooter');
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -80,7 +80,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
await retry.try(async function () {
|
||||
return !testSubjects.exists('pagination-button-1'); // only page 0 is left
|
||||
});
|
||||
await testSubjects.existOrFail('discoverTableFooter');
|
||||
await testSubjects.existOrFail('unifiedDataTableFooter');
|
||||
});
|
||||
|
||||
it('should render exact number of rows which where configured in the saved search or in settings', async () => {
|
||||
|
|
|
@ -1496,6 +1496,8 @@
|
|||
"@kbn/ui-shared-deps-src/*": ["packages/kbn-ui-shared-deps-src/*"],
|
||||
"@kbn/ui-theme": ["packages/kbn-ui-theme"],
|
||||
"@kbn/ui-theme/*": ["packages/kbn-ui-theme/*"],
|
||||
"@kbn/unified-data-table": ["packages/kbn-unified-data-table"],
|
||||
"@kbn/unified-data-table/*": ["packages/kbn-unified-data-table/*"],
|
||||
"@kbn/unified-doc-viewer": ["packages/kbn-unified-doc-viewer"],
|
||||
"@kbn/unified-doc-viewer/*": ["packages/kbn-unified-doc-viewer/*"],
|
||||
"@kbn/unified-doc-viewer-examples": ["examples/unified_doc_viewer"],
|
||||
|
|
|
@ -2178,11 +2178,6 @@
|
|||
"discover.dscTour.stepAddFields.description": "Cliquez sur {plusIcon} pour ajouter les champs qui vous intéressent.",
|
||||
"discover.dscTour.stepExpand.description": "Cliquez sur {expandIcon} pour afficher, comparer et filtrer les documents.",
|
||||
"discover.errorCalloutFormattedTitle": "{title} : {errorMessage}",
|
||||
"discover.grid.copyClipboardButtonTitle": "Copier la valeur de {column}",
|
||||
"discover.grid.copyColumnValuesToClipboard.toastTitle": "Valeurs de la colonne \"{column}\" copiées dans le presse-papiers",
|
||||
"discover.grid.filterForAria": "Filtrer sur cette {value}",
|
||||
"discover.grid.filterOutAria": "Exclure cette {value}",
|
||||
"discover.gridSampleSize.limitDescription": "Les résultats de recherche sont limités à {sampleSize} documents Ajoutez d'autres termes pour affiner votre recherche.",
|
||||
"discover.howToSeeOtherMatchingDocumentsDescription": "Voici les {sampleSize} premiers documents correspondant à votre recherche. Veuillez affiner cette dernière pour en voir davantage.",
|
||||
"discover.noMatchRoute.bannerText": "L'application Discover ne reconnaît pas cet itinéraire : {route}",
|
||||
"discover.noResults.kqlExamples.kqlDescription": "En savoir plus sur {kqlLink}",
|
||||
|
@ -2192,9 +2187,6 @@
|
|||
"discover.pageTitleWithSavedSearch": "Discover –{savedSearchTitle}",
|
||||
"discover.savedSearchAliasMatchRedirect.objectNoun": "Recherche {savedSearch}",
|
||||
"discover.savedSearchURLConflictCallout.objectNoun": "Recherche {savedSearch}",
|
||||
"discover.searchGenerationWithDescription": "Tableau généré par la recherche {searchTitle}",
|
||||
"discover.searchGenerationWithDescriptionGrid": "Tableau généré par la recherche {searchTitle} ({searchDescription})",
|
||||
"discover.selectedDocumentsNumber": "{nr} documents sélectionnés",
|
||||
"discover.showingDefaultDataViewWarningDescription": "Affichage de la vue de données par défaut : \"{loadedDataViewTitle}\" ({loadedDataViewId})",
|
||||
"discover.showingSavedDataViewWarningDescription": "Affichage de la vue de données enregistrée : \"{ownDataViewTitle}\" ({ownDataViewId})",
|
||||
"discover.singleDocRoute.errorMessage": "Aucune vue de données correspondante pour l'ID {dataViewId}",
|
||||
|
@ -2247,7 +2239,6 @@
|
|||
"discover.backToTopLinkText": "Revenir en haut de la page.",
|
||||
"discover.badge.readOnly.text": "Lecture seule",
|
||||
"discover.badge.readOnly.tooltip": "Impossible d’enregistrer les recherches",
|
||||
"discover.clearSelection": "Effacer la sélection",
|
||||
"discover.confirmDataViewSave.cancel": "Annuler",
|
||||
"discover.confirmDataViewSave.message": "L'action que vous avez choisie requiert une vue de données enregistrée.",
|
||||
"discover.confirmDataViewSave.saveAndContinue": "Enregistrer et continuer",
|
||||
|
@ -2268,8 +2259,6 @@
|
|||
"discover.context.unableToLoadAnchorDocumentDescription": "Impossible de charger le document ancré",
|
||||
"discover.context.unableToLoadDocumentDescription": "Impossible de charger les documents",
|
||||
"discover.contextViewRoute.errorTitle": "Une erreur s'est produite",
|
||||
"discover.controlColumnHeader": "Colonne de commande",
|
||||
"discover.copyToClipboardJSON": "Copier les documents dans le presse-papiers (JSON)",
|
||||
"discover.discoverBreadcrumbTitle": "Discover",
|
||||
"discover.discoverDefaultSearchSessionName": "Discover",
|
||||
"discover.discoverDescription": "Explorez vos données de manière interactive en interrogeant et en filtrant des documents bruts.",
|
||||
|
@ -2368,29 +2357,15 @@
|
|||
"discover.fieldChooser.discoverField.removeFieldTooltip": "Supprimer le champ du tableau",
|
||||
"unifiedDocViewer.fieldChooser.discoverField.value": "Valeur",
|
||||
"discover.goToDiscoverButtonText": "Aller à Discover",
|
||||
"discover.grid.closePopover": "Fermer la fenêtre contextuelle",
|
||||
"discover.grid.copyCellValueButton": "Copier la valeur",
|
||||
"discover.grid.copyColumnNameToClipboard.toastTitle": "Copié dans le presse-papiers",
|
||||
"discover.grid.copyColumnNameToClipBoardButton": "Copier le nom",
|
||||
"discover.grid.copyColumnValuesToClipBoardButton": "Copier la colonne",
|
||||
"discover.grid.copyEscapedValueWithFormulasToClipboardWarningText": "Les valeurs peuvent contenir des formules avec échappement.",
|
||||
"discover.grid.copyFailedErrorText": "Impossible de copier dans le presse-papiers avec ce navigateur",
|
||||
"discover.grid.copyValueToClipboard.toastTitle": "Copié dans le presse-papiers",
|
||||
"discover.grid.documentHeader": "Document",
|
||||
"discover.grid.editFieldButton": "Modifier le champ de la vue de données",
|
||||
"discover.grid.filterFor": "Filtrer sur",
|
||||
"discover.grid.filterOut": "Exclure",
|
||||
"discover.grid.flyout.documentNavigation": "Navigation dans le document",
|
||||
"discover.grid.flyout.toastColumnAdded": "La colonne \"{columnName}\" a été ajoutée.",
|
||||
"discover.grid.flyout.toastColumnRemoved": "La colonne \"{columnName}\" a été supprimée.",
|
||||
"discover.grid.selectDoc": "Sélectionner le document \"{rowNumber}\"",
|
||||
"discover.grid.tableRow.detailHeading": "Document développé",
|
||||
"discover.grid.tableRow.textBasedDetailHeading": "Ligne développée",
|
||||
"discover.grid.tableRow.viewSingleDocumentLinkTextSimple": "Document unique",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsHover": "Inspectez des documents qui ont été créés avant et après ce document. Seuls les filtres épinglés restent actifs dans la vue Documents relatifs.",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple": "Documents relatifs",
|
||||
"discover.grid.tableRow.viewText": "Afficher :",
|
||||
"discover.grid.viewDoc": "Afficher/Masquer les détails de la boîte de dialogue",
|
||||
"discover.helpMenu.appName": "Découverte",
|
||||
"discover.inspectorRequestDataTitleDocuments": "Documents",
|
||||
"discover.inspectorRequestDescriptionDocument": "Cette requête interroge Elasticsearch afin de récupérer les documents.",
|
||||
|
@ -2400,7 +2375,6 @@
|
|||
"unifiedDocViewer.json.copyToClipboardLabel": "Copier dans le presse-papiers",
|
||||
"discover.loadingDocuments": "Chargement des documents",
|
||||
"unifiedDocViewer.loadingJSON": "Chargement de JSON",
|
||||
"discover.loadingResults": "Chargement des résultats",
|
||||
"discover.localMenu.alertsDescription": "Alertes",
|
||||
"discover.localMenu.fallbackReportTitle": "Recherche Discover sans titre",
|
||||
"discover.localMenu.inspectTitle": "Inspecter",
|
||||
|
@ -2443,23 +2417,18 @@
|
|||
"discover.noResults.suggestion.syntaxPopoverExampleHeader": "Exemple",
|
||||
"discover.noResults.suggestion.tryText": "Voici quelques solutions à essayer :",
|
||||
"discover.noResults.suggestion.viewAllMatchesButtonText": "Afficher toutes les correspondances",
|
||||
"discover.noResultsFound": "Résultat introuvable",
|
||||
"discover.notifications.invalidTimeRangeText": "La plage temporelle spécifiée n'est pas valide (de : \"{from}\" à \"{to}\").",
|
||||
"discover.notifications.invalidTimeRangeTitle": "Plage temporelle non valide",
|
||||
"discover.notifications.notSavedSearchTitle": "La recherche \"{savedSearchTitle}\" n'a pas été enregistrée.",
|
||||
"discover.notifications.savedSearchTitle": "La recherche \"{savedSearchTitle}\" a été enregistrée.",
|
||||
"discover.pageTitleWithoutSavedSearch": "Discover - Recherche non encore enregistrée",
|
||||
"discover.reloadSavedSearchButton": "Réinitialiser la recherche",
|
||||
"discover.removeColumnLabel": "Supprimer la colonne",
|
||||
"discover.rootBreadcrumb": "Découverte",
|
||||
"discover.sampleData.viewLinkLabel": "Découverte",
|
||||
"discover.savedSearch.savedObjectName": "Recherche enregistrée",
|
||||
"discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "Ouvrir dans Discover",
|
||||
"discover.searchingTitle": "Recherche",
|
||||
"discover.selectColumnHeader": "Sélectionner la colonne",
|
||||
"discover.serverLocatorExtension.titleFromLocatorUnknown": "Recherche inconnue",
|
||||
"discover.showAllDocuments": "Afficher tous les documents",
|
||||
"discover.showSelectedDocumentsOnly": "Afficher uniquement les documents sélectionnés",
|
||||
"discover.singleDocRoute.errorTitle": "Une erreur s'est produite",
|
||||
"discover.skipToBottomButtonLabel": "Atteindre la fin du tableau",
|
||||
"unifiedDocViewer.sourceViewer.errorMessage": "Impossible de récupérer les données pour le moment. Actualisez l'onglet et réessayez.",
|
||||
|
@ -2481,6 +2450,25 @@
|
|||
"discover.viewAlert.searchSourceErrorTitle": "Erreur lors de la récupération de la source de recherche",
|
||||
"discover.viewModes.document.label": "Documents",
|
||||
"discover.viewModes.fieldStatistics.label": "Statistiques de champ",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} – Ce champ représente l'heure à laquelle les événements se sont produits.",
|
||||
"unifiedDataTable.searchGenerationWithDescription": "Tableau généré par la recherche {searchTitle}",
|
||||
"unifiedDataTable.searchGenerationWithDescriptionGrid": "Tableau généré par la recherche {searchTitle} ({searchDescription})",
|
||||
"unifiedDataTable.selectedDocumentsNumber": "{nr} documents sélectionnés",
|
||||
"unifiedDataTable.clearSelection": "Effacer la sélection",
|
||||
"unifiedDataTable.controlColumnHeader": "Colonne de commande",
|
||||
"unifiedDataTable.copyToClipboardJSON": "Copier les documents dans le presse-papiers (JSON)",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltip": "Ce champ représente l'heure à laquelle les événements se sont produits.",
|
||||
"unifiedDataTable.grid.copyColumnNameToClipBoardButton": "Copier le nom",
|
||||
"unifiedDataTable.grid.copyColumnValuesToClipBoardButton": "Copier la colonne",
|
||||
"unifiedDataTable.grid.documentHeader": "Document",
|
||||
"unifiedDataTable.grid.editFieldButton": "Modifier le champ de la vue de données",
|
||||
"unifiedDataTable.grid.selectDoc": "Sélectionner le document \"{rowNumber}\"",
|
||||
"unifiedDataTable.loadingResults": "Chargement des résultats",
|
||||
"unifiedDataTable.noResultsFound": "Résultat introuvable",
|
||||
"unifiedDataTable.removeColumnLabel": "Supprimer la colonne",
|
||||
"unifiedDataTable.selectColumnHeader": "Sélectionner la colonne",
|
||||
"unifiedDataTable.showAllDocuments": "Afficher tous les documents",
|
||||
"unifiedDataTable.showSelectedDocumentsOnly": "Afficher uniquement les documents sélectionnés",
|
||||
"domDragDrop.announce.cancelled": "Mouvement annulé. {label} revenu à sa position initiale",
|
||||
"domDragDrop.announce.cancelledItem": "Mouvement annulé. {label} revenu au groupe {groupLabel} à la position {position}",
|
||||
"domDragDrop.announce.dropped.combineCompatible": "{label} combiné dans le groupe {groupLabel} en {dropLabel} dans le groupe {dropGroupLabel} à la position {dropPosition} dans le calque {dropLayerNumber}",
|
||||
|
|
|
@ -2193,11 +2193,6 @@
|
|||
"discover.dscTour.stepAddFields.description": "{plusIcon}をクリックして、関心があるフィールドを追加します。",
|
||||
"discover.dscTour.stepExpand.description": "{expandIcon}をクリックすると、ドキュメントを表示、比較、フィルタリングできます。",
|
||||
"discover.errorCalloutFormattedTitle": "{title}: {errorMessage}",
|
||||
"discover.grid.copyClipboardButtonTitle": "{column}の値をコピー",
|
||||
"discover.grid.copyColumnValuesToClipboard.toastTitle": "\"{column}\"列の値がクリップボードにコピーされました",
|
||||
"discover.grid.filterForAria": "この{value}でフィルターを適用",
|
||||
"discover.grid.filterOutAria": "この{value}を除外",
|
||||
"discover.gridSampleSize.limitDescription": "検索結果は{sampleSize}ドキュメントに制限されています。検索を絞り込むには、その他の検索用語を追加してください。",
|
||||
"discover.howToSeeOtherMatchingDocumentsDescription": "これらは検索条件に一致した初めの{sampleSize}件のドキュメントです。他の結果を表示するには検索条件を絞ってください。",
|
||||
"discover.noMatchRoute.bannerText": "Discoverアプリケーションはこのルートを認識できません:{route}",
|
||||
"discover.noResults.kqlExamples.kqlDescription": "{kqlLink}の詳細",
|
||||
|
@ -2207,9 +2202,6 @@
|
|||
"discover.pageTitleWithSavedSearch": "Discover - {savedSearchTitle}",
|
||||
"discover.savedSearchAliasMatchRedirect.objectNoun": "{savedSearch}検索",
|
||||
"discover.savedSearchURLConflictCallout.objectNoun": "{savedSearch}検索",
|
||||
"discover.searchGenerationWithDescription": "検索{searchTitle}で生成されたテーブル",
|
||||
"discover.searchGenerationWithDescriptionGrid": "検索{searchTitle}で生成されたテーブル({searchDescription})",
|
||||
"discover.selectedDocumentsNumber": "{nr}個のドキュメントが選択されました",
|
||||
"discover.showingDefaultDataViewWarningDescription": "デフォルトのデータビューを表示しています:\"{loadedDataViewTitle}\"({loadedDataViewId})",
|
||||
"discover.showingSavedDataViewWarningDescription": "保存されたデータビューを表示しています:\"{ownDataViewTitle}\"({ownDataViewId})",
|
||||
"discover.singleDocRoute.errorMessage": "ID {dataViewId}の一致するデータビューが見つかりません",
|
||||
|
@ -2262,7 +2254,6 @@
|
|||
"discover.backToTopLinkText": "最上部へ戻る。",
|
||||
"discover.badge.readOnly.text": "読み取り専用",
|
||||
"discover.badge.readOnly.tooltip": "検索を保存できません",
|
||||
"discover.clearSelection": "選択した項目をクリア",
|
||||
"discover.confirmDataViewSave.cancel": "キャンセル",
|
||||
"discover.confirmDataViewSave.message": "選択したアクションでは、保存されたデータビューが必要です。",
|
||||
"discover.confirmDataViewSave.saveAndContinue": "保存して続行",
|
||||
|
@ -2283,8 +2274,6 @@
|
|||
"discover.context.unableToLoadAnchorDocumentDescription": "アンカードキュメントを読み込めません",
|
||||
"discover.context.unableToLoadDocumentDescription": "ドキュメントを読み込めません",
|
||||
"discover.contextViewRoute.errorTitle": "エラーが発生しました",
|
||||
"discover.controlColumnHeader": "列の制御",
|
||||
"discover.copyToClipboardJSON": "ドキュメントをクリップボードにコピー(JSON)",
|
||||
"discover.discoverBreadcrumbTitle": "Discover",
|
||||
"discover.discoverDefaultSearchSessionName": "Discover",
|
||||
"discover.discoverDescription": "ドキュメントにクエリをかけたりフィルターを適用することで、データをインタラクティブに閲覧できます。",
|
||||
|
@ -2383,29 +2372,15 @@
|
|||
"discover.fieldChooser.discoverField.removeFieldTooltip": "フィールドを表から削除",
|
||||
"unifiedDocViewer.fieldChooser.discoverField.value": "値",
|
||||
"discover.goToDiscoverButtonText": "Discoverに移動",
|
||||
"discover.grid.closePopover": "ポップオーバーを閉じる",
|
||||
"discover.grid.copyCellValueButton": "値をコピー",
|
||||
"discover.grid.copyColumnNameToClipboard.toastTitle": "クリップボードにコピーされました",
|
||||
"discover.grid.copyColumnNameToClipBoardButton": "名前をコピー",
|
||||
"discover.grid.copyColumnValuesToClipBoardButton": "列をコピー",
|
||||
"discover.grid.copyEscapedValueWithFormulasToClipboardWarningText": "値にはエスケープされた式を含めることができます。",
|
||||
"discover.grid.copyFailedErrorText": "このブラウザーではクリップボードにコピーできません",
|
||||
"discover.grid.copyValueToClipboard.toastTitle": "クリップボードにコピーされました",
|
||||
"discover.grid.documentHeader": "ドキュメント",
|
||||
"discover.grid.editFieldButton": "データビューフィールドを編集",
|
||||
"discover.grid.filterFor": "フィルター",
|
||||
"discover.grid.filterOut": "除外",
|
||||
"discover.grid.flyout.documentNavigation": "ドキュメントナビゲーション",
|
||||
"discover.grid.flyout.toastColumnAdded": "列'{columnName}'が追加されました",
|
||||
"discover.grid.flyout.toastColumnRemoved": "列'{columnName}'が削除されました",
|
||||
"discover.grid.selectDoc": "ドキュメント'{rowNumber}'を選択",
|
||||
"discover.grid.tableRow.detailHeading": "拡張ドキュメント",
|
||||
"discover.grid.tableRow.textBasedDetailHeading": "展開された行",
|
||||
"discover.grid.tableRow.viewSingleDocumentLinkTextSimple": "1つのドキュメント",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsHover": "このドキュメントの前後に出現したドキュメントを検査します。周りのドキュメントビューでは、固定されたフィルターのみがアクティブのままです。",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple": "周りのドキュメント",
|
||||
"discover.grid.tableRow.viewText": "表示:",
|
||||
"discover.grid.viewDoc": "詳細ダイアログを切り替え",
|
||||
"discover.helpMenu.appName": "Discover",
|
||||
"discover.inspectorRequestDataTitleDocuments": "ドキュメント",
|
||||
"discover.inspectorRequestDescriptionDocument": "このリクエストはElasticsearchにクエリをかけ、ドキュメントを取得します。",
|
||||
|
@ -2415,7 +2390,6 @@
|
|||
"unifiedDocViewer.json.copyToClipboardLabel": "クリップボードにコピー",
|
||||
"discover.loadingDocuments": "ドキュメントを読み込み中",
|
||||
"unifiedDocViewer.loadingJSON": "JSONを読み込んでいます",
|
||||
"discover.loadingResults": "結果を読み込み中",
|
||||
"discover.localMenu.alertsDescription": "アラート",
|
||||
"discover.localMenu.fallbackReportTitle": "無題のDiscover検索",
|
||||
"discover.localMenu.inspectTitle": "検査",
|
||||
|
@ -2458,23 +2432,18 @@
|
|||
"discover.noResults.suggestion.syntaxPopoverExampleHeader": "例",
|
||||
"discover.noResults.suggestion.tryText": "次の方法を試してください:",
|
||||
"discover.noResults.suggestion.viewAllMatchesButtonText": "すべての一致を表示",
|
||||
"discover.noResultsFound": "結果が見つかりませんでした",
|
||||
"discover.notifications.invalidTimeRangeText": "指定された時間範囲が無効です。(開始:'{from}'、終了:'{to}')",
|
||||
"discover.notifications.invalidTimeRangeTitle": "無効な時間範囲",
|
||||
"discover.notifications.notSavedSearchTitle": "検索「{savedSearchTitle}」は保存されませんでした。",
|
||||
"discover.notifications.savedSearchTitle": "検索「{savedSearchTitle}」が保存されました。",
|
||||
"discover.pageTitleWithoutSavedSearch": "Discover - 検索は保存されていません",
|
||||
"discover.reloadSavedSearchButton": "検索をリセット",
|
||||
"discover.removeColumnLabel": "列を削除",
|
||||
"discover.rootBreadcrumb": "Discover",
|
||||
"discover.sampleData.viewLinkLabel": "Discover",
|
||||
"discover.savedSearch.savedObjectName": "保存検索",
|
||||
"discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "Discoverで開く",
|
||||
"discover.searchingTitle": "検索中",
|
||||
"discover.selectColumnHeader": "列を選択",
|
||||
"discover.serverLocatorExtension.titleFromLocatorUnknown": "不明な検索",
|
||||
"discover.showAllDocuments": "すべてのドキュメントを表示",
|
||||
"discover.showSelectedDocumentsOnly": "選択したドキュメントのみを表示",
|
||||
"discover.singleDocRoute.errorTitle": "エラーが発生しました",
|
||||
"discover.skipToBottomButtonLabel": "テーブルの最後に移動",
|
||||
"unifiedDocViewer.sourceViewer.errorMessage": "現在データを取得できませんでした。タブを更新して、再試行してください。",
|
||||
|
@ -2496,6 +2465,25 @@
|
|||
"discover.viewAlert.searchSourceErrorTitle": "検索ソースの取得エラー",
|
||||
"discover.viewModes.document.label": "ドキュメント",
|
||||
"discover.viewModes.fieldStatistics.label": "フィールド統計情報",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} - このフィールドはイベントの発生時刻を表します。",
|
||||
"unifiedDataTable.searchGenerationWithDescription": "検索{searchTitle}で生成されたテーブル",
|
||||
"unifiedDataTable.searchGenerationWithDescriptionGrid": "検索{searchTitle}で生成されたテーブル({searchDescription})",
|
||||
"unifiedDataTable.selectedDocumentsNumber": "{nr}個のドキュメントが選択されました",
|
||||
"unifiedDataTable.clearSelection": "選択した項目をクリア",
|
||||
"unifiedDataTable.controlColumnHeader": "列の制御",
|
||||
"unifiedDataTable.copyToClipboardJSON": "ドキュメントをクリップボードにコピー(JSON)",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltip": "このフィールドはイベントの発生時刻を表します。",
|
||||
"unifiedDataTable.grid.copyColumnNameToClipBoardButton": "名前をコピー",
|
||||
"unifiedDataTable.grid.copyColumnValuesToClipBoardButton": "列をコピー",
|
||||
"unifiedDataTable.grid.documentHeader": "ドキュメント",
|
||||
"unifiedDataTable.grid.editFieldButton": "データビューフィールドを編集",
|
||||
"unifiedDataTable.grid.selectDoc": "ドキュメント'{rowNumber}'を選択",
|
||||
"unifiedDataTable.loadingResults": "結果を読み込み中",
|
||||
"unifiedDataTable.noResultsFound": "結果が見つかりませんでした",
|
||||
"unifiedDataTable.removeColumnLabel": "列を削除",
|
||||
"unifiedDataTable.selectColumnHeader": "列を選択",
|
||||
"unifiedDataTable.showAllDocuments": "すべてのドキュメントを表示",
|
||||
"unifiedDataTable.showSelectedDocumentsOnly": "選択したドキュメントのみを表示",
|
||||
"domDragDrop.announce.cancelled": "移動がキャンセルされました。{label}は初期位置に戻りました",
|
||||
"domDragDrop.announce.cancelledItem": "移動がキャンセルされました。{label}は位置{position}の{groupLabel}グループに戻りました",
|
||||
"domDragDrop.announce.dropped.combineCompatible": "レイヤー{dropLayerNumber}の位置{dropPosition}でグループ{dropGroupLabel}の{dropLabel}にグループ{groupLabel}の{label}を結合しました。",
|
||||
|
|
|
@ -2193,11 +2193,6 @@
|
|||
"discover.dscTour.stepAddFields.description": "单击 {plusIcon} 以添加您感兴趣的字段。",
|
||||
"discover.dscTour.stepExpand.description": "单击 {expandIcon} 以查看、比较和筛选文档。",
|
||||
"discover.errorCalloutFormattedTitle": "{title}: {errorMessage}",
|
||||
"discover.grid.copyClipboardButtonTitle": "复制 {column} 的值",
|
||||
"discover.grid.copyColumnValuesToClipboard.toastTitle": "“{column}”列的值已复制到剪贴板",
|
||||
"discover.grid.filterForAria": "筛留此 {value}",
|
||||
"discover.grid.filterOutAria": "筛除此 {value}",
|
||||
"discover.gridSampleSize.limitDescription": "搜索结果被限定为 {sampleSize} 个文档。添加更多搜索词以缩小搜索范围。",
|
||||
"discover.howToSeeOtherMatchingDocumentsDescription": "以下是匹配您的搜索的前 {sampleSize} 个文档,请优化您的搜索以查看其他文档。",
|
||||
"discover.noMatchRoute.bannerText": "Discover 应用程序无法识别此路由:{route}",
|
||||
"discover.noResults.kqlExamples.kqlDescription": "详细了解 {kqlLink}",
|
||||
|
@ -2207,9 +2202,6 @@
|
|||
"discover.pageTitleWithSavedSearch": "Discover - {savedSearchTitle}",
|
||||
"discover.savedSearchAliasMatchRedirect.objectNoun": "{savedSearch} 搜索",
|
||||
"discover.savedSearchURLConflictCallout.objectNoun": "{savedSearch} 搜索",
|
||||
"discover.searchGenerationWithDescription": "搜索 {searchTitle} 生成的表",
|
||||
"discover.searchGenerationWithDescriptionGrid": "搜索 {searchTitle} 生成的表({searchDescription})",
|
||||
"discover.selectedDocumentsNumber": "{nr} 个文档已选择",
|
||||
"discover.showingDefaultDataViewWarningDescription": "正在显示默认数据视图:“{loadedDataViewTitle}”({loadedDataViewId})",
|
||||
"discover.showingSavedDataViewWarningDescription": "正在显示已保存数据视图:“{ownDataViewTitle}”({ownDataViewId})",
|
||||
"discover.singleDocRoute.errorMessage": "没有与 ID {dataViewId} 相匹配的数据视图",
|
||||
|
@ -2262,7 +2254,6 @@
|
|||
"discover.backToTopLinkText": "返回顶部。",
|
||||
"discover.badge.readOnly.text": "只读",
|
||||
"discover.badge.readOnly.tooltip": "无法保存搜索",
|
||||
"discover.clearSelection": "清除所选内容",
|
||||
"discover.confirmDataViewSave.cancel": "取消",
|
||||
"discover.confirmDataViewSave.message": "您选择的操作需要已保存的数据视图。",
|
||||
"discover.confirmDataViewSave.saveAndContinue": "保存并继续",
|
||||
|
@ -2283,8 +2274,6 @@
|
|||
"discover.context.unableToLoadAnchorDocumentDescription": "无法加载该定位点文档",
|
||||
"discover.context.unableToLoadDocumentDescription": "无法加载文档",
|
||||
"discover.contextViewRoute.errorTitle": "发生错误",
|
||||
"discover.controlColumnHeader": "控制列",
|
||||
"discover.copyToClipboardJSON": "将文档复制到剪贴板 (JSON)",
|
||||
"discover.discoverBreadcrumbTitle": "Discover",
|
||||
"discover.discoverDefaultSearchSessionName": "发现",
|
||||
"discover.discoverDescription": "通过查询和筛选原始文档来以交互方式浏览您的数据。",
|
||||
|
@ -2383,29 +2372,15 @@
|
|||
"discover.fieldChooser.discoverField.removeFieldTooltip": "从表中移除字段",
|
||||
"unifiedDocViewer.fieldChooser.discoverField.value": "值",
|
||||
"discover.goToDiscoverButtonText": "前往 Discover",
|
||||
"discover.grid.closePopover": "关闭弹出框",
|
||||
"discover.grid.copyCellValueButton": "复制值",
|
||||
"discover.grid.copyColumnNameToClipboard.toastTitle": "已复制到剪贴板",
|
||||
"discover.grid.copyColumnNameToClipBoardButton": "复制名称",
|
||||
"discover.grid.copyColumnValuesToClipBoardButton": "复制列",
|
||||
"discover.grid.copyEscapedValueWithFormulasToClipboardWarningText": "值可能包含已转义的公式。",
|
||||
"discover.grid.copyFailedErrorText": "无法在此浏览器中复制到剪贴板",
|
||||
"discover.grid.copyValueToClipboard.toastTitle": "已复制到剪贴板",
|
||||
"discover.grid.documentHeader": "文档",
|
||||
"discover.grid.editFieldButton": "编辑数据视图字段",
|
||||
"discover.grid.filterFor": "筛留",
|
||||
"discover.grid.filterOut": "筛除",
|
||||
"discover.grid.flyout.documentNavigation": "文档导航",
|
||||
"discover.grid.flyout.toastColumnAdded": "已添加列“{columnName}”",
|
||||
"discover.grid.flyout.toastColumnRemoved": "已移除列“{columnName}”",
|
||||
"discover.grid.selectDoc": "选择文档“{rowNumber}”",
|
||||
"discover.grid.tableRow.detailHeading": "已展开文档",
|
||||
"discover.grid.tableRow.textBasedDetailHeading": "已展开行",
|
||||
"discover.grid.tableRow.viewSingleDocumentLinkTextSimple": "单个文档",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsHover": "检查在此文档之前和之后出现的文档。在周围文档视图中,仅已固定筛选仍处于活动状态。",
|
||||
"discover.grid.tableRow.viewSurroundingDocumentsLinkTextSimple": "周围文档",
|
||||
"discover.grid.tableRow.viewText": "视图:",
|
||||
"discover.grid.viewDoc": "切换具有详情的对话框",
|
||||
"discover.helpMenu.appName": "Discover",
|
||||
"discover.inspectorRequestDataTitleDocuments": "文档",
|
||||
"discover.inspectorRequestDescriptionDocument": "此请求将查询 Elasticsearch 以获取文档。",
|
||||
|
@ -2415,7 +2390,6 @@
|
|||
"unifiedDocViewer.json.copyToClipboardLabel": "复制到剪贴板",
|
||||
"discover.loadingDocuments": "正在加载文档",
|
||||
"unifiedDocViewer.loadingJSON": "正在加载 JSON",
|
||||
"discover.loadingResults": "正在加载结果",
|
||||
"discover.localMenu.alertsDescription": "告警",
|
||||
"discover.localMenu.fallbackReportTitle": "未命名 Discover 搜索",
|
||||
"discover.localMenu.inspectTitle": "检查",
|
||||
|
@ -2458,23 +2432,18 @@
|
|||
"discover.noResults.suggestion.syntaxPopoverExampleHeader": "示例",
|
||||
"discover.noResults.suggestion.tryText": "这里是要尝试的一些内容:",
|
||||
"discover.noResults.suggestion.viewAllMatchesButtonText": "查看所有匹配项",
|
||||
"discover.noResultsFound": "找不到结果",
|
||||
"discover.notifications.invalidTimeRangeText": "提供的时间范围无效。(自:“{from}”,至:“{to}”)",
|
||||
"discover.notifications.invalidTimeRangeTitle": "时间范围无效",
|
||||
"discover.notifications.notSavedSearchTitle": "搜索“{savedSearchTitle}”未保存。",
|
||||
"discover.notifications.savedSearchTitle": "搜索“{savedSearchTitle}”已保存",
|
||||
"discover.pageTitleWithoutSavedSearch": "Discover - 尚未保存搜索",
|
||||
"discover.reloadSavedSearchButton": "重置搜索",
|
||||
"discover.removeColumnLabel": "移除列",
|
||||
"discover.rootBreadcrumb": "Discover",
|
||||
"discover.sampleData.viewLinkLabel": "Discover",
|
||||
"discover.savedSearch.savedObjectName": "已保存搜索",
|
||||
"discover.savedSearchEmbeddable.action.viewSavedSearch.displayName": "在 Discover 中打开",
|
||||
"discover.searchingTitle": "正在搜索",
|
||||
"discover.selectColumnHeader": "选择列",
|
||||
"discover.serverLocatorExtension.titleFromLocatorUnknown": "未知搜索",
|
||||
"discover.showAllDocuments": "显示所有文档",
|
||||
"discover.showSelectedDocumentsOnly": "仅显示选定的文档",
|
||||
"discover.singleDocRoute.errorTitle": "发生错误",
|
||||
"discover.skipToBottomButtonLabel": "转到表尾",
|
||||
"unifiedDocViewer.sourceViewer.errorMessage": "当前无法获取数据。请刷新选项卡以重试。",
|
||||
|
@ -2496,6 +2465,25 @@
|
|||
"discover.viewAlert.searchSourceErrorTitle": "提取搜索源时出错",
|
||||
"discover.viewModes.document.label": "文档",
|
||||
"discover.viewModes.fieldStatistics.label": "字段统计信息",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltipAriaLabel": "{timeFieldName} - 此字段表示事件发生的时间。",
|
||||
"unifiedDataTable.searchGenerationWithDescription": "搜索 {searchTitle} 生成的表",
|
||||
"unifiedDataTable.searchGenerationWithDescriptionGrid": "搜索 {searchTitle} 生成的表({searchDescription})",
|
||||
"unifiedDataTable.selectedDocumentsNumber": "{nr} 个文档已选择",
|
||||
"unifiedDataTable.clearSelection": "清除所选内容",
|
||||
"unifiedDataTable.controlColumnHeader": "控制列",
|
||||
"unifiedDataTable.copyToClipboardJSON": "将文档复制到剪贴板 (JSON)",
|
||||
"unifiedDataTable.tableHeader.timeFieldIconTooltip": "此字段表示事件发生的时间。",
|
||||
"unifiedDataTable.grid.copyColumnNameToClipBoardButton": "复制名称",
|
||||
"unifiedDataTable.grid.copyColumnValuesToClipBoardButton": "复制列",
|
||||
"unifiedDataTable.grid.documentHeader": "文档",
|
||||
"unifiedDataTable.grid.editFieldButton": "编辑数据视图字段",
|
||||
"unifiedDataTable.grid.selectDoc": "选择文档“{rowNumber}”",
|
||||
"unifiedDataTable.loadingResults": "正在加载结果",
|
||||
"unifiedDataTable.noResultsFound": "找不到结果",
|
||||
"unifiedDataTable.removeColumnLabel": "移除列",
|
||||
"unifiedDataTable.selectColumnHeader": "选择列",
|
||||
"unifiedDataTable.showAllDocuments": "显示所有文档",
|
||||
"unifiedDataTable.showSelectedDocumentsOnly": "仅显示选定的文档",
|
||||
"domDragDrop.announce.cancelled": "移动已取消。{label} 已返回至其初始位置",
|
||||
"domDragDrop.announce.cancelledItem": "移动已取消。{label} 返回至 {groupLabel} 组中的位置 {position}",
|
||||
"domDragDrop.announce.dropped.combineCompatible": "已将组 {groupLabel} 中的 {label} 组合到图层 {dropLayerNumber} 的组 {dropGroupLabel} 中的位置 {dropPosition} 上的 {dropLabel}",
|
||||
|
|
|
@ -45,7 +45,7 @@ export const DISCOVER_FIELDS_LOADING = getDataTestSubjectSelector(
|
|||
|
||||
export const DISCOVER_DATA_GRID_UPDATING = getDataTestSubjectSelector('discoverDataGridUpdating');
|
||||
|
||||
export const DISCOVER_DATA_GRID_LOADING = getDataTestSubjectSelector('discoverDataGridLoading');
|
||||
export const UNIFIED_DATA_TABLE_LOADING = getDataTestSubjectSelector('unifiedDataTableLoading');
|
||||
|
||||
export const DISCOVER_NO_RESULTS = getDataTestSubjectSelector('discoverNoResults');
|
||||
|
||||
|
@ -54,7 +54,7 @@ export const DISCOVER_TABLE = getDataTestSubjectSelector('docTable');
|
|||
export const GET_DISCOVER_DATA_GRID_CELL = (columnId: string, rowIndex: number) => {
|
||||
return `${DISCOVER_TABLE} ${getDataTestSubjectSelector(
|
||||
'dataGridRowCell'
|
||||
)}[data-gridcell-column-id="${columnId}"][data-gridcell-row-index="${rowIndex}"] .dscDiscoverGrid__cellValue`;
|
||||
)}[data-gridcell-column-id="${columnId}"][data-gridcell-row-index="${rowIndex}"] .unifiedDataTable__cellValue`;
|
||||
};
|
||||
|
||||
export const GET_DISCOVER_DATA_GRID_CELL_HEADER = (columnId: string) =>
|
||||
|
|
|
@ -5929,6 +5929,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/unified-data-table@link:packages/kbn-unified-data-table":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/unified-field-list-examples-plugin@link:examples/unified_field_list_examples":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue