mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Discover] Show field tokens in the grid header (#167179)
- Resolves https://github.com/elastic/kibana/issues/166906
## Summary
This PR adds field tokens to column header for the grid.
There are also additional necessary changes:
- field utils (name, description, icon) were moved from
`@kbn/unified-field-list` and `@kbn/discover-utils` to its own new
package `@kbn/field-utils`
- Unified Data Table and Unified Doc Viewer got a new prop `columnTypes`
which allows to render correct field icons for ES|QL searches (before
types were derived from the data view fields which could be misleading
in text-based searches as users can customize field names via query)
<img width="600" alt="Screenshot 2023-09-25 at 19 30 21"
src="388de9bb
-94f7-4d3e-878a-ca0da99fcec2">
### Checklist
- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
- [x] This renders correctly on smaller devices using a responsive
layout. (You can test this [in your
browser](https://www.browserstack.com/guide/responsive-testing-on-local-server))
- [x] This was checked for [cross-browser
compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
---------
Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Davis McPhee <davis.mcphee@elastic.co>
This commit is contained in:
parent
56bd62fa2f
commit
4f9e2bdf19
87 changed files with 3018 additions and 1037 deletions
1
.github/CODEOWNERS
vendored
1
.github/CODEOWNERS
vendored
|
@ -396,6 +396,7 @@ x-pack/test/functional_execution_context/plugins/alerts @elastic/kibana-core
|
|||
examples/field_formats_example @elastic/kibana-data-discovery
|
||||
src/plugins/field_formats @elastic/kibana-data-discovery
|
||||
packages/kbn-field-types @elastic/kibana-data-discovery
|
||||
packages/kbn-field-utils @elastic/kibana-data-discovery
|
||||
x-pack/plugins/file_upload @elastic/kibana-gis
|
||||
examples/files_example @elastic/appex-sharedux
|
||||
src/plugins/files_management @elastic/appex-sharedux
|
||||
|
|
|
@ -48,6 +48,7 @@
|
|||
"eventAnnotationListing": "src/plugins/event_annotation_listing",
|
||||
"eventAnnotationCommon": "packages/kbn-event-annotation-common",
|
||||
"eventAnnotationComponents": "packages/kbn-event-annotation-components",
|
||||
"fieldUtils": "packages/kbn-field-utils",
|
||||
"fieldFormats": "src/plugins/field_formats",
|
||||
"files": "src/plugins/files",
|
||||
"filesManagement": "src/plugins/files_management",
|
||||
|
|
|
@ -432,6 +432,7 @@
|
|||
"@kbn/field-formats-example-plugin": "link:examples/field_formats_example",
|
||||
"@kbn/field-formats-plugin": "link:src/plugins/field_formats",
|
||||
"@kbn/field-types": "link:packages/kbn-field-types",
|
||||
"@kbn/field-utils": "link:packages/kbn-field-utils",
|
||||
"@kbn/file-upload-plugin": "link:x-pack/plugins/file_upload",
|
||||
"@kbn/files-example-plugin": "link:examples/files_example",
|
||||
"@kbn/files-management-plugin": "link:src/plugins/files_management",
|
||||
|
|
|
@ -16,8 +16,6 @@ export {
|
|||
ENABLE_ESQL,
|
||||
FIELDS_LIMIT_SETTING,
|
||||
HIDE_ANNOUNCEMENTS,
|
||||
KNOWN_FIELD_TYPE_LIST,
|
||||
KNOWN_FIELD_TYPES,
|
||||
MAX_DOC_FIELDS_DISPLAYED,
|
||||
MODIFY_COLUMNS_ON_SWITCH,
|
||||
ROW_HEIGHT_OPTION,
|
||||
|
@ -36,10 +34,8 @@ export {
|
|||
formatFieldValue,
|
||||
formatHit,
|
||||
getDocId,
|
||||
getFieldTypeName,
|
||||
getIgnoredReason,
|
||||
getShouldShowFieldHandler,
|
||||
isKnownFieldType,
|
||||
isNestedFieldParent,
|
||||
usePager,
|
||||
} from './src';
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import type { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
|
||||
|
||||
export type { FieldTypeKnown, IgnoredReason, ShouldShowFieldInTableHandler } from './utils';
|
||||
export type { IgnoredReason, ShouldShowFieldInTableHandler } from './utils';
|
||||
|
||||
export interface EsHitRecord extends Omit<SearchHit, '_source'> {
|
||||
_source?: Record<string, unknown>;
|
||||
|
@ -35,3 +35,14 @@ export interface DataTableRecord {
|
|||
*/
|
||||
isAnchor?: boolean;
|
||||
}
|
||||
|
||||
type FormattedHitPair = readonly [
|
||||
fieldDisplayName: string,
|
||||
formattedValue: string,
|
||||
fieldName: string | null // `null` is when number of fields is limited and there is an extra pair about it
|
||||
];
|
||||
|
||||
/**
|
||||
* Pairs array for each field in the hit
|
||||
*/
|
||||
export type FormattedHit = FormattedHitPair[];
|
||||
|
|
|
@ -41,11 +41,11 @@ describe('formatHit', () => {
|
|||
fieldFormatsMock
|
||||
);
|
||||
expect(formatted).toEqual([
|
||||
['extension', 'formatted:png'],
|
||||
['message', 'formatted:foobar'],
|
||||
['object.value', 'formatted:42,13'],
|
||||
['_index', 'formatted:logs'],
|
||||
['_score', undefined],
|
||||
['extension', 'formatted:png', 'extension'],
|
||||
['message', 'formatted:foobar', 'message'],
|
||||
['object.value', 'formatted:42,13', 'object.value'],
|
||||
['_index', 'formatted:logs', '_index'],
|
||||
['_score', undefined, '_score'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -83,9 +83,9 @@ describe('formatHit', () => {
|
|||
fieldFormatsMock
|
||||
);
|
||||
expect(formatted).toEqual([
|
||||
['extension', 'formatted:png'],
|
||||
['message', 'formatted:foobar'],
|
||||
['and 3 more fields', ''],
|
||||
['extension', 'formatted:png', 'extension'],
|
||||
['message', 'formatted:foobar', 'message'],
|
||||
['and 3 more fields', '', null],
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -98,10 +98,10 @@ describe('formatHit', () => {
|
|||
fieldFormatsMock
|
||||
);
|
||||
expect(formatted).toEqual([
|
||||
['message', 'formatted:foobar'],
|
||||
['object.value', 'formatted:42,13'],
|
||||
['_index', 'formatted:logs'],
|
||||
['_score', undefined],
|
||||
['message', 'formatted:foobar', 'message'],
|
||||
['object.value', 'formatted:42,13', 'object.value'],
|
||||
['_index', 'formatted:logs', '_index'],
|
||||
['_score', undefined, '_score'],
|
||||
]);
|
||||
});
|
||||
|
||||
|
@ -114,9 +114,9 @@ describe('formatHit', () => {
|
|||
fieldFormatsMock
|
||||
);
|
||||
expect(formatted).toEqual([
|
||||
['bytesDisplayName', 'formatted:123'],
|
||||
['_index', 'formatted:logs'],
|
||||
['_score', undefined],
|
||||
['bytesDisplayName', 'formatted:123', 'bytes'],
|
||||
['_index', 'formatted:logs', '_index'],
|
||||
['_score', undefined, '_score'],
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -10,20 +10,23 @@ import type { SearchHit } from '@elastic/elasticsearch/lib/api/typesWithBodyKey'
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import type { DataTableRecord, ShouldShowFieldInTableHandler } from '../types';
|
||||
import type { DataTableRecord, ShouldShowFieldInTableHandler, FormattedHit } from '../types';
|
||||
import { formatFieldValue } from './format_value';
|
||||
|
||||
const formattedHitCache = new WeakMap<SearchHit, FormattedHit>();
|
||||
|
||||
type FormattedHit = Array<readonly [fieldName: string, formattedValue: string]>;
|
||||
const formattedHitCache = new WeakMap<
|
||||
SearchHit,
|
||||
{ formattedHit: FormattedHit; maxEntries: number }
|
||||
>();
|
||||
|
||||
/**
|
||||
* Returns a formatted document in form of key/value pairs of the fields name and a formatted value.
|
||||
* The value returned in each pair is an HTML string which is safe to be applied to the DOM, since
|
||||
* it's formatted using field formatters.
|
||||
* @param hit The hit to format
|
||||
* @param dataView The corresponding data view
|
||||
* @param shouldShowFieldHandler A function to check a field.
|
||||
* @param hit
|
||||
* @param dataView
|
||||
* @param shouldShowFieldHandler
|
||||
* @param maxEntries
|
||||
* @param fieldFormats
|
||||
*/
|
||||
export function formatHit(
|
||||
hit: DataTableRecord,
|
||||
|
@ -33,40 +36,35 @@ export function formatHit(
|
|||
fieldFormats: FieldFormatsStart
|
||||
): FormattedHit {
|
||||
const cached = formattedHitCache.get(hit.raw);
|
||||
if (cached) {
|
||||
return cached;
|
||||
if (cached && cached.maxEntries === maxEntries) {
|
||||
return cached.formattedHit;
|
||||
}
|
||||
|
||||
const highlights = hit.raw.highlight ?? {};
|
||||
// Flatten the object using the flattenHit implementation we use across Discover for flattening documents.
|
||||
const flattened = hit.flattened;
|
||||
|
||||
const highlightPairs: Array<[fieldName: string, formattedValue: string]> = [];
|
||||
const sourcePairs: Array<[fieldName: string, formattedValue: string]> = [];
|
||||
const highlightPairs: FormattedHit = [];
|
||||
const sourcePairs: FormattedHit = [];
|
||||
|
||||
// Add each flattened field into the corresponding array for highlighted or other fields,
|
||||
// depending on whether the original hit had a highlight for it. That way we can later
|
||||
// put highlighted fields first in the document summary.
|
||||
Object.entries(flattened).forEach(([key, val]) => {
|
||||
// Retrieve the (display) name of the fields, if it's a mapped field on the data view
|
||||
const displayKey = dataView.fields.getByName(key)?.displayName;
|
||||
const field = dataView.fields.getByName(key);
|
||||
const displayKey = field?.displayName;
|
||||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||
// Format the raw value using the regular field formatters for that field
|
||||
const formattedValue = formatFieldValue(
|
||||
val,
|
||||
hit.raw,
|
||||
fieldFormats,
|
||||
dataView,
|
||||
dataView.fields.getByName(key)
|
||||
);
|
||||
const formattedValue = formatFieldValue(val, hit.raw, fieldFormats, dataView, field);
|
||||
// If the field was a mapped field, we validate it against the fieldsToShow list, if not
|
||||
// we always include it into the result.
|
||||
if (displayKey) {
|
||||
if (shouldShowFieldHandler(key)) {
|
||||
pairs.push([displayKey, formattedValue]);
|
||||
pairs.push([displayKey, formattedValue, key]);
|
||||
}
|
||||
} else {
|
||||
pairs.push([key, formattedValue]);
|
||||
pairs.push([key, formattedValue, key]);
|
||||
}
|
||||
});
|
||||
const pairs = [...highlightPairs, ...sourcePairs];
|
||||
|
@ -83,8 +81,9 @@ export function formatHit(
|
|||
values: { count: pairs.length - maxEntries },
|
||||
}),
|
||||
'',
|
||||
null,
|
||||
] as const,
|
||||
];
|
||||
formattedHitCache.set(hit.raw, formatted);
|
||||
formattedHitCache.set(hit.raw, { formattedHit: formatted, maxEntries });
|
||||
return formatted;
|
||||
}
|
||||
|
|
|
@ -7,11 +7,9 @@
|
|||
*/
|
||||
|
||||
export * from './build_data_record';
|
||||
export * from './field_types';
|
||||
export * from './format_hit';
|
||||
export * from './format_value';
|
||||
export * from './get_doc_id';
|
||||
export * from './get_field_type_name';
|
||||
export * from './get_ignored_reason';
|
||||
export * from './get_should_show_field_handler';
|
||||
export * from './nested_fields';
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
export type {
|
||||
DataTableRecord,
|
||||
EsHitRecord,
|
||||
FieldTypeKnown,
|
||||
IgnoredReason,
|
||||
ShouldShowFieldInTableHandler,
|
||||
FormattedHit,
|
||||
} from './src/types';
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
import { htmlIdGenerator, EuiFlexItem, EuiPanel, EuiText } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useExistingFieldsReader, getFieldIconType } from '@kbn/unified-field-list';
|
||||
import { getFieldIconType } from '@kbn/field-utils';
|
||||
import { useExistingFieldsReader } from '@kbn/unified-field-list';
|
||||
import {
|
||||
FieldOption,
|
||||
FieldOptionValue,
|
||||
|
|
|
@ -15,10 +15,10 @@
|
|||
"target/**/*"
|
||||
],
|
||||
"kbn_references": [
|
||||
"@kbn/i18n",
|
||||
"@kbn/visualization-ui-components",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/chart-icons",
|
||||
"@kbn/i18n",
|
||||
"@kbn/visualization-ui-components",
|
||||
"@kbn/ui-theme",
|
||||
"@kbn/chart-icons",
|
||||
"@kbn/unified-field-list",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/data-plugin",
|
||||
|
@ -28,5 +28,6 @@
|
|||
"@kbn/i18n-react",
|
||||
"@kbn/saved-objects-finder-plugin",
|
||||
"@kbn/expressions-plugin",
|
||||
"@kbn/field-utils"
|
||||
]
|
||||
}
|
||||
|
|
3
packages/kbn-field-utils/README.md
Normal file
3
packages/kbn-field-utils/README.md
Normal file
|
@ -0,0 +1,3 @@
|
|||
# @kbn/field-utils
|
||||
|
||||
Utils for rendering fields
|
22
packages/kbn-field-utils/index.ts
Normal file
22
packages/kbn-field-utils/index.ts
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
export type { FieldTypeKnown, FieldBase } from './types';
|
||||
|
||||
export {
|
||||
isKnownFieldType,
|
||||
KNOWN_FIELD_TYPES,
|
||||
KNOWN_FIELD_TYPE_LIST,
|
||||
} from './src/utils/field_types';
|
||||
|
||||
export { getFieldIconType } from './src/utils/get_field_icon_type';
|
||||
export { getFieldType } from './src/utils/get_field_type';
|
||||
export { getFieldTypeDescription } from './src/utils/get_field_type_description';
|
||||
export { getFieldTypeName, UNKNOWN_FIELD_TYPE_MESSAGE } from './src/utils/get_field_type_name';
|
||||
|
||||
export { FieldIcon, type FieldIconProps, getFieldIconProps } from './src/components/field_icon';
|
|
@ -6,6 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export { getFieldTypeDescription } from './get_field_type_description';
|
||||
export { getFieldType } from './get_field_type';
|
||||
export { getFieldIconType } from './get_field_icon_type';
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../..',
|
||||
roots: ['<rootDir>/packages/kbn-field-utils'],
|
||||
};
|
5
packages/kbn-field-utils/kibana.jsonc
Normal file
5
packages/kbn-field-utils/kibana.jsonc
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"type": "shared-common",
|
||||
"id": "@kbn/field-utils",
|
||||
"owner": "@elastic/kibana-data-discovery"
|
||||
}
|
7
packages/kbn-field-utils/package.json
Normal file
7
packages/kbn-field-utils/package.json
Normal file
|
@ -0,0 +1,7 @@
|
|||
{
|
||||
"name": "@kbn/field-utils",
|
||||
"private": true,
|
||||
"version": "1.0.0",
|
||||
"license": "SSPL-1.0 OR Elastic License 2.0",
|
||||
"sideEffects": false
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`UnifiedFieldList <FieldIcon /> accepts additional props 1`] = `
|
||||
exports[`FieldUtils <FieldIcon /> accepts additional props 1`] = `
|
||||
<FieldIcon
|
||||
fill="none"
|
||||
label="Date"
|
||||
|
@ -9,14 +9,14 @@ exports[`UnifiedFieldList <FieldIcon /> accepts additional props 1`] = `
|
|||
/>
|
||||
`;
|
||||
|
||||
exports[`UnifiedFieldList <FieldIcon /> renders Document type properly 1`] = `
|
||||
exports[`FieldUtils <FieldIcon /> renders Document type properly 1`] = `
|
||||
<FieldIcon
|
||||
label="Records"
|
||||
type="number"
|
||||
/>
|
||||
`;
|
||||
|
||||
exports[`UnifiedFieldList <FieldIcon /> renders properly 1`] = `
|
||||
exports[`FieldUtils <FieldIcon /> renders properly 1`] = `
|
||||
<FieldIcon
|
||||
label="Date"
|
||||
scripted={false}
|
||||
|
@ -24,7 +24,7 @@ exports[`UnifiedFieldList <FieldIcon /> renders properly 1`] = `
|
|||
/>
|
||||
`;
|
||||
|
||||
exports[`UnifiedFieldList <FieldIcon /> renders properly scripted fields 1`] = `
|
||||
exports[`FieldUtils <FieldIcon /> renders properly scripted fields 1`] = `
|
||||
<FieldIcon
|
||||
label="Date"
|
||||
scripted={true}
|
|
@ -15,7 +15,7 @@ import { getFieldIconProps } from './get_field_icon_props';
|
|||
const dateField = dataView.getFieldByName('@timestamp')!;
|
||||
const scriptedField = dataView.getFieldByName('script date')!;
|
||||
|
||||
describe('UnifiedFieldList <FieldIcon />', () => {
|
||||
describe('FieldUtils <FieldIcon />', () => {
|
||||
test('renders properly', () => {
|
||||
const component = shallow(<FieldIcon {...getFieldIconProps(dateField)} />);
|
||||
expect(component).toMatchSnapshot();
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import { FieldIcon as KbnFieldIcon, FieldIconProps as KbnFieldIconProps } from '@kbn/react-field';
|
||||
import { getFieldTypeName } from '@kbn/discover-utils';
|
||||
import { getFieldTypeName } from '../../utils/get_field_type_name';
|
||||
|
||||
export type FieldIconProps = KbnFieldIconProps;
|
||||
|
|
@ -6,14 +6,12 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { FieldListItem } from '../../types';
|
||||
import { getFieldIconType } from '../../utils/field_types';
|
||||
import { type FieldIconProps } from './field_icon';
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { FieldIconProps } from './field_icon';
|
||||
import { getFieldIconType } from '../../utils/get_field_icon_type';
|
||||
import type { FieldBase } from '../../types';
|
||||
|
||||
export function getFieldIconProps<T extends FieldListItem = DataViewField>(
|
||||
field: T
|
||||
): FieldIconProps {
|
||||
export function getFieldIconProps<T extends FieldBase = DataViewField>(field: T): FieldIconProps {
|
||||
return {
|
||||
type: getFieldIconType(field),
|
||||
scripted: field.scripted,
|
|
@ -9,13 +9,13 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { FieldIconProps, GenericFieldIcon } from './field_icon';
|
||||
import { type FieldListItem } from '../../types';
|
||||
import { type FieldBase } from '../../types';
|
||||
|
||||
const Fallback = () => <Fragment />;
|
||||
|
||||
const LazyFieldIcon = React.lazy(() => import('./field_icon')) as GenericFieldIcon;
|
||||
|
||||
function WrappedFieldIcon<T extends FieldListItem = DataViewField>(props: FieldIconProps) {
|
||||
function WrappedFieldIcon<T extends FieldBase = DataViewField>(props: FieldIconProps) {
|
||||
return (
|
||||
<React.Suspense fallback={<Fallback />}>
|
||||
<LazyFieldIcon {...props} />
|
26
packages/kbn-field-utils/src/types.ts
Normal file
26
packages/kbn-field-utils/src/types.ts
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
|
||||
export type FieldTypeKnown = Exclude<
|
||||
DataViewField['timeSeriesMetric'] | DataViewField['type'],
|
||||
undefined
|
||||
>;
|
||||
|
||||
export interface FieldBase {
|
||||
name: DataViewField['name'];
|
||||
type?: DataViewField['type'];
|
||||
displayName?: DataViewField['displayName'];
|
||||
count?: DataViewField['count'];
|
||||
timeSeriesMetric?: DataViewField['timeSeriesMetric'];
|
||||
esTypes?: DataViewField['esTypes'];
|
||||
scripted?: DataViewField['scripted'];
|
||||
}
|
||||
|
||||
export type GetCustomFieldType<T extends FieldBase> = (field: T) => FieldTypeKnown;
|
|
@ -6,12 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
|
||||
export type FieldTypeKnown = Exclude<
|
||||
DataViewField['timeSeriesMetric'] | DataViewField['type'],
|
||||
undefined
|
||||
>;
|
||||
import { type FieldTypeKnown } from '../types';
|
||||
|
||||
/**
|
||||
* Field types for which name and description are defined
|
|
@ -6,10 +6,10 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { getFieldIconType } from './get_field_icon_type';
|
||||
|
||||
describe('UnifiedFieldList getFieldIconType()', () => {
|
||||
describe('FieldUtils getFieldIconType()', () => {
|
||||
it('extracts type for non-string types', () => {
|
||||
expect(
|
||||
getFieldIconType({
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { isKnownFieldType } from '@kbn/discover-utils';
|
||||
import type { FieldListItem, GetCustomFieldType } from '../../types';
|
||||
import { isKnownFieldType } from './field_types';
|
||||
import { getFieldType } from './get_field_type';
|
||||
import type { FieldBase, GetCustomFieldType } from '../types';
|
||||
|
||||
/**
|
||||
* Returns an icon type for a field
|
||||
|
@ -17,7 +17,7 @@ import { getFieldType } from './get_field_type';
|
|||
* @param getCustomFieldType
|
||||
* @public
|
||||
*/
|
||||
export function getFieldIconType<T extends FieldListItem = DataViewField>(
|
||||
export function getFieldIconType<T extends FieldBase = DataViewField>(
|
||||
field: T,
|
||||
getCustomFieldType?: GetCustomFieldType<T>
|
||||
): string {
|
|
@ -9,7 +9,7 @@
|
|||
import { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { getFieldType } from './get_field_type';
|
||||
|
||||
describe('UnifiedFieldList getFieldType()', () => {
|
||||
describe('FieldUtils getFieldType()', () => {
|
||||
it('uses time series metric if set', () => {
|
||||
expect(
|
||||
getFieldType({
|
|
@ -7,14 +7,13 @@
|
|||
*/
|
||||
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { FieldTypeKnown } from '@kbn/discover-utils/types';
|
||||
import type { FieldListItem } from '../../types';
|
||||
import type { FieldBase, FieldTypeKnown } from '../types';
|
||||
|
||||
/**
|
||||
* Returns a field type. Time series metric type will override the original field type.
|
||||
* @param field
|
||||
*/
|
||||
export function getFieldType<T extends FieldListItem = DataViewField>(field: T): FieldTypeKnown {
|
||||
export function getFieldType<T extends FieldBase = DataViewField>(field: T): FieldTypeKnown {
|
||||
const timeSeriesMetric = field.timeSeriesMetric;
|
||||
if (timeSeriesMetric) {
|
||||
return timeSeriesMetric;
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
import { getFieldTypeDescription, UNKNOWN_FIELD_TYPE_DESC } from './get_field_type_description';
|
||||
import { KNOWN_FIELD_TYPES } from '@kbn/discover-utils';
|
||||
import { KNOWN_FIELD_TYPES } from './field_types';
|
||||
|
||||
describe('UnifiedFieldList getFieldTypeDescription()', () => {
|
||||
describe('FieldUtils getFieldTypeDescription()', () => {
|
||||
describe('known field types should be recognized', () => {
|
||||
it.each(Object.values(KNOWN_FIELD_TYPES))(
|
||||
`'%s' should return a string that does not match '${UNKNOWN_FIELD_TYPE_DESC}'`,
|
|
@ -8,13 +8,13 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||
import { KNOWN_FIELD_TYPES } from '@kbn/discover-utils';
|
||||
import { KNOWN_FIELD_TYPES } from './field_types';
|
||||
|
||||
/**
|
||||
* A user-friendly description of an unknown field type
|
||||
*/
|
||||
export const UNKNOWN_FIELD_TYPE_DESC = i18n.translate(
|
||||
'unifiedFieldList.fieldNameDescription.unknownField',
|
||||
'fieldUtils.fieldNameDescription.unknownField',
|
||||
{
|
||||
defaultMessage: 'Unknown field',
|
||||
}
|
||||
|
@ -33,110 +33,110 @@ export function getFieldTypeDescription(type?: string) {
|
|||
const knownType: KNOWN_FIELD_TYPES = type as KNOWN_FIELD_TYPES;
|
||||
switch (knownType) {
|
||||
case KNOWN_FIELD_TYPES.DOCUMENT:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.recordField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.recordField', {
|
||||
defaultMessage: 'Count of records.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.BINARY:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.binaryField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.binaryField', {
|
||||
defaultMessage: 'Binary value encoded as a Base64 string.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.BOOLEAN:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.booleanField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.booleanField', {
|
||||
defaultMessage: 'True and false values.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.CONFLICT:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.conflictField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.conflictField', {
|
||||
defaultMessage: 'Field has values of different types. Resolve in Management > Data Views.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.COUNTER:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.counterField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.counterField', {
|
||||
defaultMessage:
|
||||
'A number that only increases or resets to 0 (zero). Available only for numeric and aggregate_metric_double fields.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DATE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.dateField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.dateField', {
|
||||
defaultMessage: 'A date string or the number of seconds or milliseconds since 1/1/1970.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DATE_RANGE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.dateRangeField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.dateRangeField', {
|
||||
defaultMessage: 'Range of date values.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DENSE_VECTOR:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.denseVectorField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.denseVectorField', {
|
||||
defaultMessage: 'Records dense vectors of float values.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GAUGE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.gaugeField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.gaugeField', {
|
||||
defaultMessage:
|
||||
'A number that can increase or decrease. Available only for numeric and aggregate_metric_double fields.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GEO_POINT:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.geoPointField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.geoPointField', {
|
||||
defaultMessage: 'Latitude and longitude points.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GEO_SHAPE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.geoShapeField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.geoShapeField', {
|
||||
defaultMessage: 'Complex shapes, such as polygons.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.HISTOGRAM:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.histogramField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.histogramField', {
|
||||
defaultMessage: 'Pre-aggregated numerical values in the form of a histogram.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.IP:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.ipAddressField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.ipAddressField', {
|
||||
defaultMessage: 'IPv4 and IPv6 addresses.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.IP_RANGE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.ipAddressRangeField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.ipAddressRangeField', {
|
||||
defaultMessage: 'Range of ip values supporting either IPv4 or IPv6 (or mixed) addresses.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.FLATTENED:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.flattenedField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.flattenedField', {
|
||||
defaultMessage: 'An entire JSON object as a single field value.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.MURMUR3:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.murmur3Field', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.murmur3Field', {
|
||||
defaultMessage: 'Field that computes and stores hashes of values.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.NUMBER:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.numberField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.numberField', {
|
||||
defaultMessage: 'Long, integer, short, byte, double, and float values.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.RANK_FEATURE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.rankFeatureField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.rankFeatureField', {
|
||||
defaultMessage: 'Records a numeric feature to boost hits at query time.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.RANK_FEATURES:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.rankFeaturesField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.rankFeaturesField', {
|
||||
defaultMessage: 'Records numeric features to boost hits at query time.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.POINT:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.pointField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.pointField', {
|
||||
defaultMessage: 'Arbitrary cartesian points.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.SHAPE:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.shapeField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.shapeField', {
|
||||
defaultMessage: 'Arbitrary cartesian geometries.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.STRING:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.stringField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.stringField', {
|
||||
defaultMessage: 'Full text such as the body of an email or a product description.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.TEXT:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.textField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.textField', {
|
||||
defaultMessage: 'Full text such as the body of an email or a product description.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.KEYWORD:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.keywordField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.keywordField', {
|
||||
defaultMessage:
|
||||
'Structured content such as an ID, email address, hostname, status code, or tag.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.NESTED:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.nestedField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.nestedField', {
|
||||
defaultMessage: 'JSON object that preserves the relationship between its subfields.',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.VERSION:
|
||||
return i18n.translate('unifiedFieldList.fieldNameDescription.versionField', {
|
||||
return i18n.translate('fieldUtils.fieldNameDescription.versionField', {
|
||||
defaultMessage: 'Software versions. Supports "Semantic Versioning" precedence rules.',
|
||||
});
|
||||
default:
|
|
@ -9,7 +9,7 @@
|
|||
import { getFieldTypeName, UNKNOWN_FIELD_TYPE_MESSAGE } from './get_field_type_name';
|
||||
import { KNOWN_FIELD_TYPES } from './field_types';
|
||||
|
||||
describe('UnifiedFieldList getFieldTypeName()', () => {
|
||||
describe('FieldUtils getFieldTypeName()', () => {
|
||||
describe('known field types should be recognized', () => {
|
||||
it.each(Object.values(KNOWN_FIELD_TYPES))(
|
||||
`'%s' should return a string that does not match '${UNKNOWN_FIELD_TYPE_MESSAGE}'`,
|
|
@ -14,7 +14,7 @@ import { KNOWN_FIELD_TYPES } from './field_types';
|
|||
* A user-friendly name of an unknown field type
|
||||
*/
|
||||
export const UNKNOWN_FIELD_TYPE_MESSAGE = i18n.translate(
|
||||
'discover.fieldNameIcons.unknownFieldAriaLabel',
|
||||
'fieldUtils.fieldNameIcons.unknownFieldAriaLabel',
|
||||
{
|
||||
defaultMessage: 'Unknown field',
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ export function getFieldTypeName(type?: string) {
|
|||
|
||||
if (type === 'source') {
|
||||
// Note that this type is currently not provided, type for _source is undefined
|
||||
return i18n.translate('discover.fieldNameIcons.sourceFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.sourceFieldAriaLabel', {
|
||||
defaultMessage: 'Source field',
|
||||
});
|
||||
}
|
||||
|
@ -40,107 +40,107 @@ export function getFieldTypeName(type?: string) {
|
|||
const knownType: KNOWN_FIELD_TYPES = type as KNOWN_FIELD_TYPES;
|
||||
switch (knownType) {
|
||||
case KNOWN_FIELD_TYPES.DOCUMENT:
|
||||
return i18n.translate('discover.fieldNameIcons.recordAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.recordAriaLabel', {
|
||||
defaultMessage: 'Records',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.BINARY:
|
||||
return i18n.translate('discover.fieldNameIcons.binaryAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.binaryAriaLabel', {
|
||||
defaultMessage: 'Binary',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.BOOLEAN:
|
||||
return i18n.translate('discover.fieldNameIcons.booleanAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.booleanAriaLabel', {
|
||||
defaultMessage: 'Boolean',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.CONFLICT:
|
||||
return i18n.translate('discover.fieldNameIcons.conflictFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.conflictFieldAriaLabel', {
|
||||
defaultMessage: 'Conflict',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.COUNTER:
|
||||
return i18n.translate('discover.fieldNameIcons.counterFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.counterFieldAriaLabel', {
|
||||
defaultMessage: 'Counter metric',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DATE:
|
||||
return i18n.translate('discover.fieldNameIcons.dateFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.dateFieldAriaLabel', {
|
||||
defaultMessage: 'Date',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DATE_RANGE:
|
||||
return i18n.translate('discover.fieldNameIcons.dateRangeFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.dateRangeFieldAriaLabel', {
|
||||
defaultMessage: 'Date range',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.DENSE_VECTOR:
|
||||
return i18n.translate('discover.fieldNameIcons.denseVectorFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.denseVectorFieldAriaLabel', {
|
||||
defaultMessage: 'Dense vector',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GAUGE:
|
||||
return i18n.translate('discover.fieldNameIcons.gaugeFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.gaugeFieldAriaLabel', {
|
||||
defaultMessage: 'Gauge metric',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GEO_POINT:
|
||||
return i18n.translate('discover.fieldNameIcons.geoPointFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.geoPointFieldAriaLabel', {
|
||||
defaultMessage: 'Geo point',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.GEO_SHAPE:
|
||||
return i18n.translate('discover.fieldNameIcons.geoShapeFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.geoShapeFieldAriaLabel', {
|
||||
defaultMessage: 'Geo shape',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.HISTOGRAM:
|
||||
return i18n.translate('discover.fieldNameIcons.histogramFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.histogramFieldAriaLabel', {
|
||||
defaultMessage: 'Histogram',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.IP:
|
||||
return i18n.translate('discover.fieldNameIcons.ipAddressFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.ipAddressFieldAriaLabel', {
|
||||
defaultMessage: 'IP address',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.IP_RANGE:
|
||||
return i18n.translate('discover.fieldNameIcons.ipRangeFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.ipRangeFieldAriaLabel', {
|
||||
defaultMessage: 'IP range',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.FLATTENED:
|
||||
return i18n.translate('discover.fieldNameIcons.flattenedFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.flattenedFieldAriaLabel', {
|
||||
defaultMessage: 'Flattened',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.MURMUR3:
|
||||
return i18n.translate('discover.fieldNameIcons.murmur3FieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.murmur3FieldAriaLabel', {
|
||||
defaultMessage: 'Murmur3',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.NUMBER:
|
||||
return i18n.translate('discover.fieldNameIcons.numberFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.numberFieldAriaLabel', {
|
||||
defaultMessage: 'Number',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.RANK_FEATURE:
|
||||
return i18n.translate('discover.fieldNameIcons.rankFeatureFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.rankFeatureFieldAriaLabel', {
|
||||
defaultMessage: 'Rank feature',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.RANK_FEATURES:
|
||||
return i18n.translate('discover.fieldNameIcons.rankFeaturesFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.rankFeaturesFieldAriaLabel', {
|
||||
defaultMessage: 'Rank features',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.POINT:
|
||||
return i18n.translate('discover.fieldNameIcons.pointFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.pointFieldAriaLabel', {
|
||||
defaultMessage: 'Point',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.SHAPE:
|
||||
return i18n.translate('discover.fieldNameIcons.shapeFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.shapeFieldAriaLabel', {
|
||||
defaultMessage: 'Shape',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.STRING:
|
||||
return i18n.translate('discover.fieldNameIcons.stringFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.stringFieldAriaLabel', {
|
||||
defaultMessage: 'String',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.TEXT:
|
||||
return i18n.translate('discover.fieldNameIcons.textFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.textFieldAriaLabel', {
|
||||
defaultMessage: 'Text',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.KEYWORD:
|
||||
return i18n.translate('discover.fieldNameIcons.keywordFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.keywordFieldAriaLabel', {
|
||||
defaultMessage: 'Keyword',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.NESTED:
|
||||
return i18n.translate('discover.fieldNameIcons.nestedFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.nestedFieldAriaLabel', {
|
||||
defaultMessage: 'Nested',
|
||||
});
|
||||
case KNOWN_FIELD_TYPES.VERSION:
|
||||
return i18n.translate('discover.fieldNameIcons.versionFieldAriaLabel', {
|
||||
return i18n.translate('fieldUtils.fieldNameIcons.versionFieldAriaLabel', {
|
||||
defaultMessage: 'Version',
|
||||
});
|
||||
default:
|
14
packages/kbn-field-utils/tsconfig.json
Normal file
14
packages/kbn-field-utils/tsconfig.json
Normal file
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "target/types"
|
||||
},
|
||||
"include": ["*.ts", "src/**/*", "__mocks__/**/*.ts"],
|
||||
"kbn_references": [
|
||||
"@kbn/i18n",
|
||||
"@kbn/data-views-plugin",
|
||||
"@kbn/react-field",
|
||||
"@kbn/field-types",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
9
packages/kbn-field-utils/types.ts
Normal file
9
packages/kbn-field-utils/types.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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 type { FieldTypeKnown, FieldBase } from './src/types';
|
|
@ -9,6 +9,7 @@
|
|||
export { UnifiedDataTable, DataLoadingState } from './src/components/data_table';
|
||||
export type { UnifiedDataTableProps } from './src/components/data_table';
|
||||
export { getDisplayedColumns } from './src/utils/columns';
|
||||
export { getTextBasedColumnTypes } from './src/utils/get_column_types';
|
||||
export { ROWS_HEIGHT_OPTIONS } from './src/constants';
|
||||
|
||||
export { JSONCodeEditorCommonMemoized } from './src/components/json_code_editor/json_code_editor_common';
|
||||
|
|
1720
packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap
generated
Normal file
1720
packages/kbn-unified-data-table/src/components/__snapshots__/data_table_columns.test.tsx.snap
generated
Normal file
File diff suppressed because it is too large
Load diff
|
@ -324,27 +324,36 @@ describe('UnifiedDataTable', () => {
|
|||
});
|
||||
|
||||
it('should render provided in renderDocumentView DocumentView on expand clicked', async () => {
|
||||
const expandedDoc = {
|
||||
id: 'test',
|
||||
raw: {
|
||||
_index: 'test_i',
|
||||
_id: 'test',
|
||||
},
|
||||
flattened: { test: jest.fn() },
|
||||
};
|
||||
const columnTypesOverride = { testField: 'number ' };
|
||||
const renderDocumentViewMock = jest.fn((hit: DataTableRecord) => (
|
||||
<div data-test-subj="test-document-view">{hit.id}</div>
|
||||
));
|
||||
|
||||
const component = await getComponent({
|
||||
...getProps(),
|
||||
expandedDoc: {
|
||||
id: 'test',
|
||||
raw: {
|
||||
_index: 'test_i',
|
||||
_id: 'test',
|
||||
},
|
||||
flattened: { test: jest.fn() },
|
||||
},
|
||||
expandedDoc,
|
||||
setExpandedDoc: jest.fn(),
|
||||
renderDocumentView: (
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[]
|
||||
) => <div data-test-subj="test-document-view">{hit.id}</div>,
|
||||
columnTypes: columnTypesOverride,
|
||||
renderDocumentView: renderDocumentViewMock,
|
||||
externalControlColumns: [testLeadingControlColumn],
|
||||
});
|
||||
|
||||
findTestSubject(component, 'docTableExpandToggleColumn').first().simulate('click');
|
||||
expect(findTestSubject(component, 'test-document-view').exists()).toBeTruthy();
|
||||
expect(renderDocumentViewMock).toHaveBeenLastCalledWith(
|
||||
expandedDoc,
|
||||
getProps().rows,
|
||||
['_source'],
|
||||
columnTypesOverride
|
||||
);
|
||||
});
|
||||
|
||||
describe('externalAdditionalControls', () => {
|
||||
|
|
|
@ -43,7 +43,11 @@ 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 { UnifiedDataTableSettings, ValueToStringConverter } from '../types';
|
||||
import type {
|
||||
UnifiedDataTableSettings,
|
||||
ValueToStringConverter,
|
||||
DataTableColumnTypes,
|
||||
} from '../types';
|
||||
import { getDisplayedColumns } from '../utils/columns';
|
||||
import { convertValueToString } from '../utils/convert_value_to_string';
|
||||
import { getRowsPerPageOptions } from '../utils/rows_per_page';
|
||||
|
@ -75,6 +79,9 @@ interface SortObj {
|
|||
direction: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unified Data Table props
|
||||
*/
|
||||
export interface UnifiedDataTableProps {
|
||||
/**
|
||||
* Determines which element labels the grid for ARIA
|
||||
|
@ -88,6 +95,16 @@ export interface UnifiedDataTableProps {
|
|||
* Determines ids of the columns which are displayed
|
||||
*/
|
||||
columns: string[];
|
||||
/**
|
||||
* If not provided, types will be derived by default from the dataView field types.
|
||||
* For displaying text-based search results, pass column types (which are available separately in the fetch request) down here.
|
||||
* Check available utils in `utils/get_column_types.ts`
|
||||
*/
|
||||
columnTypes?: DataTableColumnTypes;
|
||||
/**
|
||||
* Field tokens could be rendered in column header next to the field name.
|
||||
*/
|
||||
showColumnTokens?: boolean;
|
||||
/**
|
||||
* If set, the given document is displayed in a flyout
|
||||
*/
|
||||
|
@ -214,7 +231,8 @@ export interface UnifiedDataTableProps {
|
|||
renderDocumentView?: (
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[]
|
||||
displayedColumns: string[],
|
||||
columnTypes?: DataTableColumnTypes
|
||||
) => JSX.Element | undefined;
|
||||
/**
|
||||
* Optional value for providing configuration setting for UnifiedDataTable rows height
|
||||
|
@ -300,6 +318,8 @@ const CONTROL_COLUMN_IDS_DEFAULT = ['openDetails', 'select'];
|
|||
export const UnifiedDataTable = ({
|
||||
ariaLabelledBy,
|
||||
columns,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
controlColumnIds = CONTROL_COLUMN_IDS_DEFAULT,
|
||||
dataView,
|
||||
loadingState,
|
||||
|
@ -509,16 +529,16 @@ export const UnifiedDataTable = ({
|
|||
*/
|
||||
const renderCellValue = useMemo(
|
||||
() =>
|
||||
getRenderCellValueFn(
|
||||
getRenderCellValueFn({
|
||||
dataView,
|
||||
displayedRows,
|
||||
rows: displayedRows,
|
||||
useNewFieldsApi,
|
||||
shouldShowFieldHandler,
|
||||
() => dataGridRef.current?.closeCellPopover(),
|
||||
services.fieldFormats,
|
||||
maxDocFieldsDisplayed,
|
||||
externalCustomRenderers
|
||||
),
|
||||
closePopover: () => dataGridRef.current?.closeCellPopover(),
|
||||
fieldFormats: services.fieldFormats,
|
||||
maxEntries: maxDocFieldsDisplayed,
|
||||
externalCustomRenderers,
|
||||
}),
|
||||
[
|
||||
dataView,
|
||||
displayedRows,
|
||||
|
@ -616,6 +636,8 @@ export const UnifiedDataTable = ({
|
|||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
}),
|
||||
[
|
||||
onFilter,
|
||||
|
@ -633,6 +655,8 @@ export const UnifiedDataTable = ({
|
|||
valueToStringConverter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
]
|
||||
);
|
||||
|
||||
|
@ -841,7 +865,7 @@ export const UnifiedDataTable = ({
|
|||
)}
|
||||
{canSetExpandedDoc &&
|
||||
expandedDoc &&
|
||||
renderDocumentView!(expandedDoc, displayedRows, displayedColumns)}
|
||||
renderDocumentView!(expandedDoc, displayedRows, displayedColumns, columnTypes)}
|
||||
</span>
|
||||
</UnifiedDataTableContext.Provider>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* 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, { ReactElement } from 'react';
|
||||
import { FieldIcon } from '@kbn/field-utils';
|
||||
import { mountWithIntl } from '@kbn/test-jest-helpers';
|
||||
import {
|
||||
createStubDataView,
|
||||
stubLogstashDataView,
|
||||
} from '@kbn/data-views-plugin/common/data_view.stub';
|
||||
import { DataTableColumnHeader } from './data_table_column_header';
|
||||
|
||||
const stubDataViewWithNested = createStubDataView({
|
||||
spec: {
|
||||
id: 'index_with_nested',
|
||||
fields: {
|
||||
'nested_user.lastname': {
|
||||
name: 'nested_user.lastname',
|
||||
esTypes: ['text'],
|
||||
type: 'string',
|
||||
aggregatable: false,
|
||||
searchable: true,
|
||||
subType: {
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
'nested_user.lastname.keyword': {
|
||||
name: 'nested_user.lastname.keyword',
|
||||
esTypes: ['keyword'],
|
||||
type: 'string',
|
||||
aggregatable: true,
|
||||
searchable: true,
|
||||
subType: {
|
||||
multi: {
|
||||
parent: 'nested_user.lastname',
|
||||
},
|
||||
nested: {
|
||||
path: 'nested_user',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
title: 'index_with_nested',
|
||||
},
|
||||
});
|
||||
|
||||
describe('DataTableColumnHeader', function () {
|
||||
async function mountComponent(element: ReactElement) {
|
||||
const component = mountWithIntl(element);
|
||||
// wait for lazy modules
|
||||
await new Promise((resolve) => setTimeout(resolve, 0));
|
||||
component.update();
|
||||
|
||||
return component;
|
||||
}
|
||||
it('should render a correct token', async () => {
|
||||
const component = await mountComponent(
|
||||
<DataTableColumnHeader
|
||||
columnName="bytes"
|
||||
columnDisplayName="bytesDisplayName"
|
||||
dataView={stubLogstashDataView}
|
||||
/>
|
||||
);
|
||||
expect(component.text()).toBe('NumberbytesDisplayName');
|
||||
expect(component.find(FieldIcon).first().prop('type')).toBe('number');
|
||||
});
|
||||
|
||||
it('should render a correct token for a custom column type (in case of text-based queries)', async () => {
|
||||
const component = await mountComponent(
|
||||
<DataTableColumnHeader
|
||||
columnName="bytes"
|
||||
columnDisplayName="bytesDisplayName"
|
||||
columnTypes={{
|
||||
bytes: 'keyword',
|
||||
}}
|
||||
dataView={stubLogstashDataView}
|
||||
/>
|
||||
);
|
||||
expect(component.text()).toBe('KeywordbytesDisplayName');
|
||||
expect(component.find(FieldIcon).first().prop('type')).toBe('keyword');
|
||||
});
|
||||
|
||||
it('should not render a token for Document column', async () => {
|
||||
const component = await mountComponent(
|
||||
<DataTableColumnHeader
|
||||
columnName="_source"
|
||||
columnDisplayName="Document"
|
||||
dataView={stubLogstashDataView}
|
||||
/>
|
||||
);
|
||||
expect(component.text()).toBe('Document');
|
||||
expect(component.find(FieldIcon).exists()).toBe(false);
|
||||
});
|
||||
|
||||
it('should render the nested icon', async () => {
|
||||
const component = await mountComponent(
|
||||
<DataTableColumnHeader
|
||||
columnName="nested_user"
|
||||
columnDisplayName="Nested User"
|
||||
dataView={stubDataViewWithNested}
|
||||
/>
|
||||
);
|
||||
expect(component.text()).toBe('NestedNested User');
|
||||
expect(component.find(FieldIcon).first().prop('type')).toBe('nested');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,83 @@
|
|||
/*
|
||||
* 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, { useMemo } from 'react';
|
||||
import { css } from '@emotion/react';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import type { DataView } from '@kbn/data-views-plugin/common';
|
||||
import { FieldIcon, getFieldIconProps } from '@kbn/field-utils';
|
||||
import { isNestedFieldParent } from '@kbn/discover-utils';
|
||||
import type { DataTableColumnTypes } from '../types';
|
||||
|
||||
interface DataTableColumnHeaderProps {
|
||||
dataView: DataView;
|
||||
columnName: string | null;
|
||||
columnDisplayName: string;
|
||||
columnTypes?: DataTableColumnTypes;
|
||||
}
|
||||
|
||||
export const DataTableColumnHeader: React.FC<DataTableColumnHeaderProps> = (props) => {
|
||||
const { columnDisplayName, columnName, columnTypes, dataView } = props;
|
||||
const columnToken = useMemo(
|
||||
() => getRenderedToken({ columnName, columnTypes, dataView }),
|
||||
[columnName, columnTypes, dataView]
|
||||
);
|
||||
|
||||
return (
|
||||
<EuiFlexGroup
|
||||
direction="row"
|
||||
wrap={false}
|
||||
responsive={false}
|
||||
alignItems="center"
|
||||
gutterSize="xs"
|
||||
css={css`
|
||||
.euiDataGridHeaderCell--numeric & {
|
||||
justify-content: flex-end;
|
||||
}
|
||||
`}
|
||||
>
|
||||
{columnToken && <EuiFlexItem grow={false}>{columnToken}</EuiFlexItem>}
|
||||
<EuiFlexItem
|
||||
grow={false}
|
||||
className="eui-displayInline eui-textTruncate"
|
||||
data-test-subj="unifiedDataTableColumnTitle"
|
||||
>
|
||||
{columnDisplayName}
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
function getRenderedToken({
|
||||
dataView,
|
||||
columnName,
|
||||
columnTypes,
|
||||
}: Pick<DataTableColumnHeaderProps, 'dataView' | 'columnName' | 'columnTypes'>) {
|
||||
if (!columnName || columnName === '_source') {
|
||||
return null;
|
||||
}
|
||||
|
||||
// for text-based searches
|
||||
if (columnTypes) {
|
||||
return columnTypes[columnName] && columnTypes[columnName] !== 'unknown' ? ( // renders an icon or nothing
|
||||
<FieldIcon type={columnTypes[columnName]} />
|
||||
) : null;
|
||||
}
|
||||
|
||||
const dataViewField = dataView.getFieldByName(columnName);
|
||||
|
||||
if (dataViewField) {
|
||||
return <FieldIcon {...getFieldIconProps(dataViewField)} />;
|
||||
}
|
||||
|
||||
if (isNestedFieldParent(columnName, dataView)) {
|
||||
return <FieldIcon type="nested" />;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
|
@ -39,102 +39,7 @@ describe('Data table columns', function () {
|
|||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": false,
|
||||
"showMoveLeft": false,
|
||||
"showMoveRight": false,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "extension",
|
||||
"id": "extension",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": false,
|
||||
"showMoveLeft": false,
|
||||
"showMoveRight": false,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "message",
|
||||
"id": "message",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns eui grid columns with time column', async () => {
|
||||
|
@ -155,174 +60,7 @@ describe('Data table columns', function () {
|
|||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": false,
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"display": <div
|
||||
aria-label="timestamp - this field represents the time that events occurred."
|
||||
>
|
||||
<EuiToolTip
|
||||
content="This field represents the time that events occurred."
|
||||
delay="regular"
|
||||
display="inlineBlock"
|
||||
position="top"
|
||||
>
|
||||
<React.Fragment>
|
||||
timestamp
|
||||
|
||||
<EuiIcon
|
||||
type="clock"
|
||||
/>
|
||||
</React.Fragment>
|
||||
</EuiToolTip>
|
||||
</div>,
|
||||
"displayAsText": "timestamp",
|
||||
"id": "timestamp",
|
||||
"initialWidth": 212,
|
||||
"isSortable": true,
|
||||
"schema": "datetime",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": Object {
|
||||
"iconType": "cross",
|
||||
"label": "Remove column",
|
||||
},
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "extension",
|
||||
"id": "extension",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": Object {
|
||||
"iconType": "cross",
|
||||
"label": "Remove column",
|
||||
},
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "message",
|
||||
"id": "message",
|
||||
"isSortable": false,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns eui grid with in memory sorting', async () => {
|
||||
|
@ -343,174 +81,7 @@ describe('Data table columns', function () {
|
|||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchInlineSnapshot(`
|
||||
Array [
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": false,
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"display": <div
|
||||
aria-label="timestamp - this field represents the time that events occurred."
|
||||
>
|
||||
<EuiToolTip
|
||||
content="This field represents the time that events occurred."
|
||||
delay="regular"
|
||||
display="inlineBlock"
|
||||
position="top"
|
||||
>
|
||||
<React.Fragment>
|
||||
timestamp
|
||||
|
||||
<EuiIcon
|
||||
type="clock"
|
||||
/>
|
||||
</React.Fragment>
|
||||
</EuiToolTip>
|
||||
</div>,
|
||||
"displayAsText": "timestamp",
|
||||
"id": "timestamp",
|
||||
"initialWidth": 212,
|
||||
"isSortable": true,
|
||||
"schema": "datetime",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": Object {
|
||||
"iconType": "cross",
|
||||
"label": "Remove column",
|
||||
},
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
[Function],
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "extension",
|
||||
"id": "extension",
|
||||
"isSortable": true,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
Object {
|
||||
"actions": Object {
|
||||
"additional": Array [
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnNameToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy name"
|
||||
id="unifiedDataTable.grid.copyColumnNameToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
Object {
|
||||
"data-test-subj": "gridCopyColumnValuesToClipBoardButton",
|
||||
"iconProps": Object {
|
||||
"size": "m",
|
||||
},
|
||||
"iconType": "copyClipboard",
|
||||
"label": <FormattedMessage
|
||||
defaultMessage="Copy column"
|
||||
id="unifiedDataTable.grid.copyColumnValuesToClipBoardButton"
|
||||
values={Object {}}
|
||||
/>,
|
||||
"onClick": [Function],
|
||||
"size": "xs",
|
||||
},
|
||||
],
|
||||
"showHide": Object {
|
||||
"iconType": "cross",
|
||||
"label": "Remove column",
|
||||
},
|
||||
"showMoveLeft": true,
|
||||
"showMoveRight": true,
|
||||
},
|
||||
"cellActions": Array [
|
||||
[Function],
|
||||
],
|
||||
"displayAsText": "message",
|
||||
"id": "message",
|
||||
"isSortable": true,
|
||||
"schema": "string",
|
||||
"visibleCellActions": undefined,
|
||||
},
|
||||
]
|
||||
`);
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -538,4 +109,54 @@ describe('Data table columns', function () {
|
|||
expect(actual).toEqual(['timestamp', 'extension', 'message']);
|
||||
});
|
||||
});
|
||||
|
||||
describe('column tokens', () => {
|
||||
it('returns eui grid columns with tokens', async () => {
|
||||
const actual = getEuiGridColumns({
|
||||
showColumnTokens: true,
|
||||
columns: columnsWithTimeCol,
|
||||
settings: {},
|
||||
dataView: dataViewWithTimefieldMock,
|
||||
defaultColumns: false,
|
||||
isSortEnabled: true,
|
||||
isPlainRecord: false,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 100,
|
||||
services: {
|
||||
uiSettings: servicesMock.uiSettings,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
},
|
||||
hasEditDataViewPermission: () =>
|
||||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns eui grid columns with tokens for custom column types', async () => {
|
||||
const actual = getEuiGridColumns({
|
||||
showColumnTokens: true,
|
||||
columnTypes: {
|
||||
extension: 'number',
|
||||
message: 'keyword',
|
||||
},
|
||||
columns,
|
||||
settings: {},
|
||||
dataView: dataViewWithTimefieldMock,
|
||||
defaultColumns: false,
|
||||
isSortEnabled: true,
|
||||
isPlainRecord: false,
|
||||
valueToStringConverter: dataTableContextMock.valueToStringConverter,
|
||||
rowsCount: 100,
|
||||
services: {
|
||||
uiSettings: servicesMock.uiSettings,
|
||||
toastNotifications: servicesMock.toastNotifications,
|
||||
},
|
||||
hasEditDataViewPermission: () =>
|
||||
servicesMock.dataViewFieldEditor.userPermissions.editIndexPattern(),
|
||||
onFilter: () => {},
|
||||
});
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -20,13 +20,16 @@ import { ToastsStart, IUiSettingsClient } from '@kbn/core/public';
|
|||
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 type { ValueToStringConverter, DataTableColumnTypes } 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';
|
||||
import { DataTableColumnHeader } from './data_table_column_header';
|
||||
|
||||
const DataTableColumnHeaderMemoized = React.memo(DataTableColumnHeader);
|
||||
|
||||
const openDetails = {
|
||||
id: 'openDetails',
|
||||
|
@ -80,6 +83,8 @@ function buildEuiGridColumn({
|
|||
editField,
|
||||
columnCellActions,
|
||||
visibleCellActions,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
}: {
|
||||
columnName: string;
|
||||
columnWidth: number | undefined;
|
||||
|
@ -95,6 +100,8 @@ function buildEuiGridColumn({
|
|||
editField?: (fieldName: string) => void;
|
||||
columnCellActions?: EuiDataGridColumnCellAction[];
|
||||
visibleCellActions?: number;
|
||||
columnTypes?: DataTableColumnTypes;
|
||||
showColumnTokens?: boolean;
|
||||
}) {
|
||||
const dataViewField = dataView.getFieldByName(columnName);
|
||||
const editFieldButton =
|
||||
|
@ -122,6 +129,14 @@ function buildEuiGridColumn({
|
|||
id: columnName,
|
||||
schema: getSchemaByKbnType(dataViewField?.type),
|
||||
isSortable: isSortEnabled && (isPlainRecord || dataViewField?.sortable === true),
|
||||
display: showColumnTokens ? (
|
||||
<DataTableColumnHeaderMemoized
|
||||
dataView={dataView}
|
||||
columnName={columnName}
|
||||
columnDisplayName={columnDisplayName}
|
||||
columnTypes={columnTypes}
|
||||
/>
|
||||
) : undefined,
|
||||
displayAsText: columnDisplayName,
|
||||
actions: {
|
||||
showHide:
|
||||
|
@ -203,6 +218,8 @@ export function getEuiGridColumns({
|
|||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
}: {
|
||||
columns: string[];
|
||||
columnsCellActions?: EuiDataGridColumnCellAction[][];
|
||||
|
@ -221,6 +238,8 @@ export function getEuiGridColumns({
|
|||
onFilter: DocViewFilterFn;
|
||||
editField?: (fieldName: string) => void;
|
||||
visibleCellActions?: number;
|
||||
columnTypes?: DataTableColumnTypes;
|
||||
showColumnTokens?: boolean;
|
||||
}) {
|
||||
const getColWidth = (column: string) => settings?.columns?.[column]?.width ?? 0;
|
||||
|
||||
|
@ -240,6 +259,8 @@ export function getEuiGridColumns({
|
|||
onFilter,
|
||||
editField,
|
||||
visibleCellActions,
|
||||
columnTypes,
|
||||
showColumnTokens,
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -22,3 +22,8 @@ export type ValueToStringConverter = (
|
|||
columnId: string,
|
||||
options?: { compatibleWithCSV?: boolean }
|
||||
) => { formattedString: string; withFormula: boolean };
|
||||
|
||||
/**
|
||||
* Custom column types per column name
|
||||
*/
|
||||
export type DataTableColumnTypes = Record<string, string>;
|
||||
|
|
|
@ -0,0 +1,46 @@
|
|||
/*
|
||||
* 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 { getTextBasedColumnTypes } from './get_column_types';
|
||||
|
||||
describe('getColumnTypes', () => {
|
||||
describe('getTextBasedColumnTypes', () => {
|
||||
test('returns a correct column types map', async () => {
|
||||
const result = getTextBasedColumnTypes([
|
||||
{
|
||||
id: '@timestamp',
|
||||
name: '@timestamp',
|
||||
meta: {
|
||||
type: 'date',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'agent.keyword',
|
||||
name: 'agent.keyword',
|
||||
meta: {
|
||||
type: 'string',
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'bytes',
|
||||
name: 'bytes',
|
||||
meta: {
|
||||
type: 'number',
|
||||
},
|
||||
},
|
||||
]);
|
||||
expect(result).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"@timestamp": "date",
|
||||
"agent.keyword": "string",
|
||||
"bytes": "number",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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 { DatatableColumn, DatatableColumnType } from '@kbn/expressions-plugin/common';
|
||||
|
||||
type TextBasedColumnTypes = Record<string, DatatableColumnType>;
|
||||
|
||||
/**
|
||||
* Column types for text based searches
|
||||
* @param textBasedColumns
|
||||
*/
|
||||
export const getTextBasedColumnTypes = (
|
||||
textBasedColumns: DatatableColumn[]
|
||||
): TextBasedColumnTypes => {
|
||||
return textBasedColumns.reduce<TextBasedColumnTypes>((map, next) => {
|
||||
map[next.name] = next.meta.type;
|
||||
return map;
|
||||
}, {});
|
||||
};
|
|
@ -105,15 +105,15 @@ const build = (hit: EsHitRecord) => buildDataTableRecord(hit, dataViewMock);
|
|||
|
||||
describe('Unified data table cell rendering', function () {
|
||||
it('renders bytes column correctly', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -131,15 +131,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders bytes column correctly using _source when details is true', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -158,15 +158,15 @@ describe('Unified data table cell rendering', function () {
|
|||
|
||||
it('renders bytes column correctly using fields when details is true', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
false,
|
||||
() => false,
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFields.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: closePopoverMockFn,
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = mountWithIntl(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -186,15 +186,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders _source column correctly', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: (fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -269,15 +269,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders _source column correctly when isDetails is set to true', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -345,15 +345,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders fields-based column correctly', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFields.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -432,16 +432,16 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('limits amount of rendered items', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFields.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) => ['extension', 'bytes'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
// this is the number of rendered items
|
||||
1
|
||||
);
|
||||
maxEntries: 1,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -477,41 +477,13 @@ describe('Unified data table cell rendering', function () {
|
|||
<EuiDescriptionListTitle
|
||||
className="unifiedDataTable__descriptionListTitle"
|
||||
>
|
||||
bytesDisplayName
|
||||
and 3 more fields
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": Array [
|
||||
100,
|
||||
],
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiDescriptionListTitle
|
||||
className="unifiedDataTable__descriptionListTitle"
|
||||
>
|
||||
_index
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": "test",
|
||||
}
|
||||
}
|
||||
/>
|
||||
<EuiDescriptionListTitle
|
||||
className="unifiedDataTable__descriptionListTitle"
|
||||
>
|
||||
_score
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
dangerouslySetInnerHTML={
|
||||
Object {
|
||||
"__html": 1,
|
||||
"__html": "",
|
||||
}
|
||||
}
|
||||
/>
|
||||
|
@ -520,15 +492,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders fields-based column correctly when isDetails is set to true', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFields.map(build),
|
||||
true,
|
||||
(fieldName) => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFields.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -601,15 +573,16 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('collect object fields and renders them like _source', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
(fieldName) => ['object.value', 'extension', 'bytes'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsWithTopLevelObject.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) =>
|
||||
['object.value', 'extension', 'bytes'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -646,15 +619,16 @@ describe('Unified data table cell rendering', function () {
|
|||
|
||||
it('collect object fields and renders them like _source with fallback for unmapped', () => {
|
||||
(dataViewMock.getFieldByName as jest.Mock).mockReturnValueOnce(undefined);
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
(fieldName) => ['extension', 'bytes', 'object.value'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsWithTopLevelObject.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) =>
|
||||
['extension', 'bytes', 'object.value'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -691,15 +665,15 @@ describe('Unified data table cell rendering', function () {
|
|||
|
||||
it('collect object fields and renders them as json in details', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsWithTopLevelObject.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: closePopoverMockFn,
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -759,15 +733,15 @@ describe('Unified data table cell rendering', function () {
|
|||
|
||||
it('renders a functional close button when CodeEditor is rendered', () => {
|
||||
const closePopoverMockFn = jest.fn();
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
closePopoverMockFn,
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsWithTopLevelObject.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: closePopoverMockFn,
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = mountWithIntl(
|
||||
<KibanaContextProvider services={mockServices}>
|
||||
<DataTableCellValue
|
||||
|
@ -788,15 +762,15 @@ describe('Unified data table 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 DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsWithTopLevelObject.map(build),
|
||||
true,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsWithTopLevelObject.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -823,15 +797,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders correctly when invalid row is given', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={1}
|
||||
|
@ -849,15 +823,15 @@ describe('Unified data table cell rendering', function () {
|
|||
});
|
||||
|
||||
it('renders correctly when invalid column is given', () => {
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsSource.map(build),
|
||||
false,
|
||||
() => false,
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsSource.map(build),
|
||||
useNewFieldsApi: false,
|
||||
shouldShowFieldHandler: () => false,
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
@ -888,15 +862,15 @@ describe('Unified data table cell rendering', function () {
|
|||
},
|
||||
},
|
||||
];
|
||||
const DataTableCellValue = getRenderCellValueFn(
|
||||
dataViewMock,
|
||||
rowsFieldsUnmapped.map(build),
|
||||
true,
|
||||
(fieldName) => ['unmapped'].includes(fieldName),
|
||||
jest.fn(),
|
||||
mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
100
|
||||
);
|
||||
const DataTableCellValue = getRenderCellValueFn({
|
||||
dataView: dataViewMock,
|
||||
rows: rowsFieldsUnmapped.map(build),
|
||||
useNewFieldsApi: true,
|
||||
shouldShowFieldHandler: (fieldName) => ['unmapped'].includes(fieldName),
|
||||
closePopover: jest.fn(),
|
||||
fieldFormats: mockServices.fieldFormats as unknown as FieldFormatsStart,
|
||||
maxEntries: 100,
|
||||
});
|
||||
const component = shallow(
|
||||
<DataTableCellValue
|
||||
rowIndex={0}
|
||||
|
|
|
@ -25,6 +25,7 @@ import type {
|
|||
DataTableRecord,
|
||||
EsHitRecord,
|
||||
ShouldShowFieldInTableHandler,
|
||||
FormattedHit,
|
||||
} from '@kbn/discover-utils/types';
|
||||
import { formatFieldValue, formatHit } from '@kbn/discover-utils';
|
||||
import { UnifiedDataTableContext } from '../table_context';
|
||||
|
@ -33,21 +34,29 @@ import JsonCodeEditor from '../components/json_code_editor/json_code_editor';
|
|||
|
||||
const CELL_CLASS = 'unifiedDataTable__cellValue';
|
||||
|
||||
export const getRenderCellValueFn =
|
||||
(
|
||||
dataView: DataView,
|
||||
rows: DataTableRecord[] | undefined,
|
||||
useNewFieldsApi: boolean,
|
||||
shouldShowFieldHandler: ShouldShowFieldInTableHandler,
|
||||
closePopover: () => void,
|
||||
fieldFormats: FieldFormatsStart,
|
||||
maxEntries: number,
|
||||
externalCustomRenderers?: Record<
|
||||
string,
|
||||
(props: EuiDataGridCellValueElementProps) => React.ReactNode
|
||||
>
|
||||
) =>
|
||||
({
|
||||
export const getRenderCellValueFn = ({
|
||||
dataView,
|
||||
rows,
|
||||
useNewFieldsApi,
|
||||
shouldShowFieldHandler,
|
||||
closePopover,
|
||||
fieldFormats,
|
||||
maxEntries,
|
||||
externalCustomRenderers,
|
||||
}: {
|
||||
dataView: DataView;
|
||||
rows: DataTableRecord[] | undefined;
|
||||
useNewFieldsApi: boolean;
|
||||
shouldShowFieldHandler: ShouldShowFieldInTableHandler;
|
||||
closePopover: () => void;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
maxEntries: number;
|
||||
externalCustomRenderers?: Record<
|
||||
string,
|
||||
(props: EuiDataGridCellValueElementProps) => React.ReactNode
|
||||
>;
|
||||
}) => {
|
||||
return ({
|
||||
rowIndex,
|
||||
columnId,
|
||||
isDetails,
|
||||
|
@ -122,7 +131,7 @@ export const getRenderCellValueFn =
|
|||
}
|
||||
|
||||
if (field?.type === '_source' || useTopLevelObjectColumns) {
|
||||
const pairs = useTopLevelObjectColumns
|
||||
const pairs: FormattedHit = useTopLevelObjectColumns
|
||||
? getTopLevelObjectPairs(row.raw, columnId, dataView, shouldShowFieldHandler).slice(
|
||||
0,
|
||||
maxEntries
|
||||
|
@ -135,10 +144,10 @@ export const getRenderCellValueFn =
|
|||
compressed
|
||||
className={classnames('unifiedDataTable__descriptionList', CELL_CLASS)}
|
||||
>
|
||||
{pairs.map(([key, value]) => (
|
||||
<Fragment key={key}>
|
||||
{pairs.map(([fieldDisplayName, value]) => (
|
||||
<Fragment key={fieldDisplayName}>
|
||||
<EuiDescriptionListTitle className="unifiedDataTable__descriptionListTitle">
|
||||
{key}
|
||||
{fieldDisplayName}
|
||||
</EuiDescriptionListTitle>
|
||||
<EuiDescriptionListDescription
|
||||
className="unifiedDataTable__descriptionListDescription"
|
||||
|
@ -161,6 +170,7 @@ export const getRenderCellValueFn =
|
|||
/>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper function to show top level objects
|
||||
|
@ -272,8 +282,8 @@ function getTopLevelObjectPairs(
|
|||
const innerColumns = getInnerColumns(row.fields as Record<string, unknown[]>, columnId);
|
||||
// Put the most important fields first
|
||||
const highlights: Record<string, unknown> = (row.highlight as Record<string, unknown>) ?? {};
|
||||
const highlightPairs: Array<[string, string]> = [];
|
||||
const sourcePairs: Array<[string, string]> = [];
|
||||
const highlightPairs: FormattedHit = [];
|
||||
const sourcePairs: FormattedHit = [];
|
||||
Object.entries(innerColumns).forEach(([key, values]) => {
|
||||
const subField = dataView.getFieldByName(key);
|
||||
const displayKey = dataView.fields.getByName
|
||||
|
@ -293,10 +303,10 @@ function getTopLevelObjectPairs(
|
|||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||
if (displayKey) {
|
||||
if (shouldShowFieldHandler(displayKey)) {
|
||||
pairs.push([displayKey, formatted]);
|
||||
pairs.push([displayKey, formatted, key]);
|
||||
}
|
||||
} else {
|
||||
pairs.push([key, formatted]);
|
||||
pairs.push([key, formatted, key]);
|
||||
}
|
||||
});
|
||||
return [...highlightPairs, ...sourcePairs];
|
||||
|
|
|
@ -33,5 +33,6 @@
|
|||
"@kbn/code-editor",
|
||||
"@kbn/config",
|
||||
"@kbn/monaco",
|
||||
"@kbn/field-utils",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -14,7 +14,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FieldIcon, FieldIconProps } from '@kbn/react-field';
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
import { getDataViewFieldSubtypeMulti } from '@kbn/es-query';
|
||||
import { getFieldTypeName } from '@kbn/discover-utils';
|
||||
import { getFieldTypeName } from '@kbn/field-utils';
|
||||
|
||||
interface Props {
|
||||
fieldName: string;
|
||||
|
|
|
@ -29,6 +29,11 @@ export interface DocViewRenderProps {
|
|||
hit: DataTableRecord;
|
||||
dataView: DataView;
|
||||
columns?: string[];
|
||||
/**
|
||||
* If not provided, types will be derived by default from the dataView field types.
|
||||
* For displaying text-based search results, define column types (which are available separately in the fetch request) here.
|
||||
*/
|
||||
columnTypes?: Record<string, string>;
|
||||
query?: Query | AggregateQuery;
|
||||
textBasedHits?: DataTableRecord[];
|
||||
filter?: DocViewFilterFn;
|
||||
|
|
|
@ -23,5 +23,6 @@
|
|||
"@kbn/i18n-react",
|
||||
"@kbn/i18n",
|
||||
"@kbn/react-field",
|
||||
"@kbn/field-utils",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
export { FieldList, type FieldListProps } from './src/components/field_list';
|
||||
export { FieldListGrouped, type FieldListGroupedProps } from './src/components/field_list_grouped';
|
||||
export { FieldListFilters, type FieldListFiltersProps } from './src/components/field_list_filters';
|
||||
export { FieldIcon, type FieldIconProps, getFieldIconProps } from './src/components/field_icon';
|
||||
export { FieldItemButton, type FieldItemButtonProps } from './src/components/field_item_button';
|
||||
export type {
|
||||
FieldTopValuesBucketProps,
|
||||
|
@ -85,8 +84,6 @@ export {
|
|||
type QuerySubscriberParams,
|
||||
} from './src/hooks/use_query_subscriber';
|
||||
|
||||
export { getFieldTypeDescription, getFieldType, getFieldIconType } from './src/utils/field_types';
|
||||
|
||||
export {
|
||||
UnifiedFieldListSidebarContainer,
|
||||
type UnifiedFieldListSidebarContainerApi,
|
||||
|
|
|
@ -12,8 +12,8 @@ import classnames from 'classnames';
|
|||
import { FieldButton, type FieldButtonProps } from '@kbn/react-field';
|
||||
import { EuiButtonIcon, EuiButtonIconProps, EuiHighlight, EuiIcon, EuiToolTip } from '@elastic/eui';
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { FieldIcon, getFieldIconProps } from '@kbn/field-utils';
|
||||
import { type FieldListItem, type GetCustomFieldType } from '../../types';
|
||||
import { FieldIcon, getFieldIconProps } from '../field_icon';
|
||||
import { fieldNameWildcardMatcher } from '../../utils/field_name_wildcard_matcher';
|
||||
import './field_item_button.scss';
|
||||
|
||||
|
|
|
@ -32,10 +32,15 @@ import type { CoreStart } from '@kbn/core-lifecycle-browser';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { FieldTypeKnown } from '@kbn/discover-utils/types';
|
||||
import { getFieldTypeName, isKnownFieldType, KNOWN_FIELD_TYPE_LIST } from '@kbn/discover-utils';
|
||||
import { FieldIcon } from '../field_icon';
|
||||
import { getFieldIconType, getFieldTypeDescription } from '../../utils/field_types';
|
||||
import {
|
||||
type FieldTypeKnown,
|
||||
getFieldIconType,
|
||||
getFieldTypeDescription,
|
||||
getFieldTypeName,
|
||||
isKnownFieldType,
|
||||
KNOWN_FIELD_TYPE_LIST,
|
||||
FieldIcon,
|
||||
} from '@kbn/field-utils';
|
||||
import type { FieldListItem, GetCustomFieldType } from '../../types';
|
||||
|
||||
const EQUAL_HEIGHT_OFFSET = 2; // to avoid changes in the header's height after "Clear all" button appears
|
||||
|
|
|
@ -10,10 +10,9 @@ import { useMemo, useState } from 'react';
|
|||
import { htmlIdGenerator } from '@elastic/eui';
|
||||
import { type DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { CoreStart } from '@kbn/core-lifecycle-browser';
|
||||
import type { FieldTypeKnown } from '@kbn/discover-utils/types';
|
||||
import { type FieldTypeKnown, getFieldIconType } from '@kbn/field-utils';
|
||||
import { type FieldListFiltersProps } from '../components/field_list_filters';
|
||||
import { type FieldListItem, GetCustomFieldType } from '../types';
|
||||
import { getFieldIconType } from '../utils/field_types';
|
||||
import { fieldNameWildcardMatcher } from '../utils/field_name_wildcard_matcher';
|
||||
|
||||
const htmlId = htmlIdGenerator('fieldList');
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
import type { DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import type { EuiButtonIconProps, EuiButtonProps } from '@elastic/eui';
|
||||
import type { FieldTypeKnown } from '@kbn/discover-utils/types';
|
||||
import type { FieldTypeKnown, FieldBase } from '@kbn/field-utils/types';
|
||||
|
||||
export interface BucketedAggregation<KeyType = string> {
|
||||
buckets: Array<{
|
||||
|
@ -48,15 +48,7 @@ export enum ExistenceFetchStatus {
|
|||
unknown = 'unknown',
|
||||
}
|
||||
|
||||
export interface FieldListItem {
|
||||
name: DataViewField['name'];
|
||||
type?: DataViewField['type'];
|
||||
displayName?: DataViewField['displayName'];
|
||||
count?: DataViewField['count'];
|
||||
timeSeriesMetric?: DataViewField['timeSeriesMetric'];
|
||||
esTypes?: DataViewField['esTypes'];
|
||||
scripted?: DataViewField['scripted'];
|
||||
}
|
||||
export type FieldListItem = FieldBase;
|
||||
|
||||
export enum FieldsGroupNames {
|
||||
SpecialFields = 'SpecialFields',
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
"@kbn/discover-utils",
|
||||
"@kbn/ebt-tools",
|
||||
"@kbn/shared-ux-button-toolbar",
|
||||
"@kbn/field-utils",
|
||||
],
|
||||
"exclude": ["target/**/*"]
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ import React, { useRef } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import useEffectOnce from 'react-use/lib/useEffectOnce';
|
||||
import { EuiComboBox, EuiComboBoxProps, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { FieldIcon } from '@kbn/unified-field-list/src/components/field_icon';
|
||||
import { FieldIcon } from '@kbn/field-utils/src/components/field_icon';
|
||||
import classNames from 'classnames';
|
||||
import type { DataType } from './types';
|
||||
import { TruncatedLabel } from './truncated_label';
|
||||
|
|
|
@ -30,6 +30,6 @@
|
|||
"@kbn/ui-theme",
|
||||
"@kbn/coloring",
|
||||
"@kbn/field-formats-plugin",
|
||||
"@kbn/unified-field-list",
|
||||
"@kbn/field-utils",
|
||||
],
|
||||
}
|
||||
|
|
|
@ -191,6 +191,7 @@ export function ContextAppContent({
|
|||
<CellActionsProvider getTriggerCompatibleActions={uiActions.getTriggerCompatibleActions}>
|
||||
<DiscoverGridMemoized
|
||||
ariaLabelledBy="surDocumentsAriaLabel"
|
||||
showColumnTokens
|
||||
columns={columns}
|
||||
rows={rows}
|
||||
dataView={dataView}
|
||||
|
|
|
@ -21,7 +21,13 @@ 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 {
|
||||
DataLoadingState,
|
||||
UnifiedDataTable,
|
||||
useColumns,
|
||||
type DataTableColumnTypes,
|
||||
getTextBasedColumnTypes,
|
||||
} from '@kbn/unified-data-table';
|
||||
import {
|
||||
DOC_HIDE_TIME_COLUMN_SETTING,
|
||||
DOC_TABLE_LEGACY,
|
||||
|
@ -62,8 +68,10 @@ const progressStyle = css`
|
|||
z-index: 2;
|
||||
`;
|
||||
|
||||
const TOUR_STEPS = { expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument };
|
||||
|
||||
const DocTableInfiniteMemoized = React.memo(DocTableInfinite);
|
||||
const DataGridMemoized = React.memo(UnifiedDataTable);
|
||||
const DiscoverGridMemoized = React.memo(UnifiedDataTable);
|
||||
|
||||
// export needs for testing
|
||||
export const onResize = (
|
||||
|
@ -198,14 +206,28 @@ function DiscoverDocumentsComponent({
|
|||
[isTextBasedQuery, columns, uiSettings, dataView.timeFieldName]
|
||||
);
|
||||
|
||||
const columnTypes: DataTableColumnTypes | undefined = useMemo(
|
||||
() =>
|
||||
documentState.textBasedQueryColumns
|
||||
? getTextBasedColumnTypes(documentState.textBasedQueryColumns)
|
||||
: undefined,
|
||||
[documentState.textBasedQueryColumns]
|
||||
);
|
||||
|
||||
const renderDocumentView = useCallback(
|
||||
(hit: DataTableRecord, displayedRows: DataTableRecord[], displayedColumns: string[]) => (
|
||||
(
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[],
|
||||
customColumnTypes?: DataTableColumnTypes
|
||||
) => (
|
||||
<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}
|
||||
columnTypes={customColumnTypes}
|
||||
savedSearchId={savedSearch.id}
|
||||
onFilter={onAddFilter}
|
||||
onRemoveColumn={onRemoveColumn}
|
||||
|
@ -277,9 +299,11 @@ function DiscoverDocumentsComponent({
|
|||
<CellActionsProvider
|
||||
getTriggerCompatibleActions={uiActions.getTriggerCompatibleActions}
|
||||
>
|
||||
<DataGridMemoized
|
||||
<DiscoverGridMemoized
|
||||
ariaLabelledBy="documentsAriaLabel"
|
||||
showColumnTokens
|
||||
columns={currentColumns}
|
||||
columnTypes={columnTypes}
|
||||
expandedDoc={expandedDoc}
|
||||
dataView={dataView}
|
||||
loadingState={
|
||||
|
@ -316,7 +340,7 @@ function DiscoverDocumentsComponent({
|
|||
services={services}
|
||||
totalHits={totalHits}
|
||||
onFetchMoreRecords={onFetchMoreRecords}
|
||||
componentsTourSteps={{ expandButton: DISCOVER_TOUR_STEP_ANCHOR_IDS.expandDocument }}
|
||||
componentsTourSteps={TOUR_STEPS}
|
||||
/>
|
||||
</CellActionsProvider>
|
||||
</div>
|
||||
|
|
|
@ -34,6 +34,7 @@ export interface DiscoverGridFlyoutProps {
|
|||
filters?: Filter[];
|
||||
query?: Query | AggregateQuery;
|
||||
columns: string[];
|
||||
columnTypes?: Record<string, string>;
|
||||
hit: DataTableRecord;
|
||||
hits?: DataTableRecord[];
|
||||
dataView: DataView;
|
||||
|
@ -57,6 +58,7 @@ export function DiscoverGridFlyout({
|
|||
hits,
|
||||
dataView,
|
||||
columns,
|
||||
columnTypes,
|
||||
savedSearchId,
|
||||
filters,
|
||||
query,
|
||||
|
@ -160,6 +162,7 @@ export function DiscoverGridFlyout({
|
|||
<UnifiedDocViewer
|
||||
hit={actualHit}
|
||||
columns={columns}
|
||||
columnTypes={columnTypes}
|
||||
dataView={dataView}
|
||||
filter={onFilter}
|
||||
onRemoveColumn={(columnName: string) => {
|
||||
|
|
|
@ -68,26 +68,32 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"also",
|
||||
"with \\"quotes\\" or 'single quotes'",
|
||||
"also",
|
||||
],
|
||||
Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"foo",
|
||||
],
|
||||
Array [
|
||||
"hello",
|
||||
"<h1>World</h1>",
|
||||
"hello",
|
||||
],
|
||||
Array [
|
||||
"number",
|
||||
42,
|
||||
"number",
|
||||
],
|
||||
Array [
|
||||
"_id",
|
||||
"a",
|
||||
"_id",
|
||||
],
|
||||
Array [
|
||||
"_score",
|
||||
1,
|
||||
"_score",
|
||||
],
|
||||
]
|
||||
}
|
||||
|
@ -112,26 +118,12 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"also",
|
||||
"with \\"quotes\\" or 'single quotes'",
|
||||
"also",
|
||||
],
|
||||
Array [
|
||||
"foo",
|
||||
"bar",
|
||||
],
|
||||
Array [
|
||||
"hello",
|
||||
"<h1>World</h1>",
|
||||
],
|
||||
Array [
|
||||
"number",
|
||||
42,
|
||||
],
|
||||
Array [
|
||||
"_id",
|
||||
"a",
|
||||
],
|
||||
Array [
|
||||
"_score",
|
||||
1,
|
||||
"and 4 more fields",
|
||||
"",
|
||||
null,
|
||||
],
|
||||
]
|
||||
}
|
||||
|
@ -153,26 +145,32 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"number",
|
||||
42,
|
||||
"number",
|
||||
],
|
||||
Array [
|
||||
"also",
|
||||
"with \\"quotes\\" or 'single quotes'",
|
||||
"also",
|
||||
],
|
||||
Array [
|
||||
"foo",
|
||||
"bar",
|
||||
"foo",
|
||||
],
|
||||
Array [
|
||||
"hello",
|
||||
"<h1>World</h1>",
|
||||
"hello",
|
||||
],
|
||||
Array [
|
||||
"_id",
|
||||
"a",
|
||||
"_id",
|
||||
],
|
||||
Array [
|
||||
"_score",
|
||||
1,
|
||||
"_score",
|
||||
],
|
||||
]
|
||||
}
|
||||
|
@ -208,6 +206,7 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"object.value",
|
||||
"formatted, formatted",
|
||||
"object.value",
|
||||
],
|
||||
]
|
||||
}
|
||||
|
@ -266,10 +265,12 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"object.keys",
|
||||
"formatted, formatted",
|
||||
"object.keys",
|
||||
],
|
||||
Array [
|
||||
"object.value",
|
||||
"formatted, formatted",
|
||||
"object.value",
|
||||
],
|
||||
]
|
||||
}
|
||||
|
@ -301,6 +302,7 @@ describe('Row formatter', () => {
|
|||
Array [
|
||||
"object.value",
|
||||
"5, 10",
|
||||
"object.value",
|
||||
],
|
||||
]
|
||||
}
|
||||
|
|
|
@ -9,13 +9,17 @@
|
|||
import React, { Fragment } from 'react';
|
||||
import type { DataView } from '@kbn/data-views-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { DataTableRecord, ShouldShowFieldInTableHandler } from '@kbn/discover-utils/types';
|
||||
import type {
|
||||
DataTableRecord,
|
||||
ShouldShowFieldInTableHandler,
|
||||
FormattedHit,
|
||||
} from '@kbn/discover-utils/types';
|
||||
import { formatHit } from '@kbn/discover-utils';
|
||||
|
||||
import './row_formatter.scss';
|
||||
|
||||
interface Props {
|
||||
defPairs: Array<readonly [string, string]>;
|
||||
defPairs: FormattedHit;
|
||||
}
|
||||
const TemplateComponent = ({ defPairs }: Props) => {
|
||||
return (
|
||||
|
@ -57,8 +61,8 @@ export const formatTopLevelObject = (
|
|||
maxEntries: number
|
||||
) => {
|
||||
const highlights = row.highlight ?? {};
|
||||
const highlightPairs: Array<[string, string]> = [];
|
||||
const sourcePairs: Array<[string, string]> = [];
|
||||
const highlightPairs: FormattedHit = [];
|
||||
const sourcePairs: FormattedHit = [];
|
||||
const sorted = Object.entries(fields).sort(([keyA], [keyB]) => keyA.localeCompare(keyB));
|
||||
sorted.forEach(([key, values]) => {
|
||||
const field = dataView.getFieldByName(key);
|
||||
|
@ -76,7 +80,7 @@ export const formatTopLevelObject = (
|
|||
)
|
||||
.join(', ');
|
||||
const pairs = highlights[key] ? highlightPairs : sourcePairs;
|
||||
pairs.push([displayKey ? displayKey : key, formatted]);
|
||||
pairs.push([displayKey ? displayKey : key, formatted, key]);
|
||||
});
|
||||
return <TemplateComponent defPairs={[...highlightPairs, ...sourcePairs].slice(0, maxEntries)} />;
|
||||
};
|
||||
|
|
|
@ -59,9 +59,8 @@ import {
|
|||
SORT_DEFAULT_ORDER_SETTING,
|
||||
buildDataTableRecord,
|
||||
} from '@kbn/discover-utils';
|
||||
import type { UnifiedDataTableProps } from '@kbn/unified-data-table';
|
||||
import type { UnifiedDataTableSettings } from '@kbn/unified-data-table';
|
||||
import { columnActions } from '@kbn/unified-data-table';
|
||||
import type { UnifiedDataTableProps, UnifiedDataTableSettings } from '@kbn/unified-data-table';
|
||||
import { columnActions, getTextBasedColumnTypes } from '@kbn/unified-data-table';
|
||||
import { VIEW_MODE, getDefaultRowsPerPage } from '../../common/constants';
|
||||
import type { ISearchEmbeddable, SearchInput, SearchOutput } from './types';
|
||||
import type { DiscoverServices } from '../build_services';
|
||||
|
@ -341,6 +340,9 @@ export class SavedSearchEmbeddable
|
|||
loading: false,
|
||||
});
|
||||
|
||||
searchProps.columnTypes = result.textBasedQueryColumns
|
||||
? getTextBasedColumnTypes(result.textBasedQueryColumns)
|
||||
: undefined;
|
||||
searchProps.rows = result.records;
|
||||
searchProps.totalHitCount = result.records.length;
|
||||
searchProps.isLoading = false;
|
||||
|
|
|
@ -43,6 +43,7 @@ export function SavedSearchEmbeddableComponent({
|
|||
{...(searchProps as DiscoverGridEmbeddableProps)} // TODO later: remove the type casting to prevent unexpected errors due to missing props!
|
||||
loadingState={searchProps.isLoading ? DataLoadingState.loading : DataLoadingState.loaded}
|
||||
showFullScreenButton={false}
|
||||
showColumnTokens
|
||||
query={query}
|
||||
className="unifiedDataTable"
|
||||
/>
|
||||
|
|
|
@ -5,13 +5,14 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import React, { memo, useCallback, useState } from 'react';
|
||||
import React, { 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 {
|
||||
DataLoadingState as DiscoverGridLoadingState,
|
||||
UnifiedDataTable,
|
||||
type DataTableColumnTypes,
|
||||
} from '@kbn/unified-data-table';
|
||||
import type { UnifiedDataTableProps } from '@kbn/unified-data-table';
|
||||
import './saved_search_grid.scss';
|
||||
|
@ -29,20 +30,26 @@ export interface DiscoverGridEmbeddableProps extends UnifiedDataTableProps {
|
|||
savedSearchId?: string;
|
||||
}
|
||||
|
||||
export const DataGridMemoized = memo(UnifiedDataTable);
|
||||
export const DiscoverGridMemoized = React.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[]) => (
|
||||
(
|
||||
hit: DataTableRecord,
|
||||
displayedRows: DataTableRecord[],
|
||||
displayedColumns: string[],
|
||||
customColumnTypes?: DataTableColumnTypes
|
||||
) => (
|
||||
<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}
|
||||
columnTypes={customColumnTypes}
|
||||
savedSearchId={props.savedSearchId}
|
||||
onFilter={props.onFilter}
|
||||
onRemoveColumn={props.onRemoveColumn}
|
||||
|
@ -69,7 +76,7 @@ export function DiscoverGridEmbeddable(props: DiscoverGridEmbeddableProps) {
|
|||
dataTestSubj="embeddedSavedSearchDocTable"
|
||||
interceptedWarnings={props.interceptedWarnings}
|
||||
>
|
||||
<DataGridMemoized
|
||||
<DiscoverGridMemoized
|
||||
{...gridProps}
|
||||
totalHits={props.totalHitCount}
|
||||
setExpandedDoc={setExpandedDoc}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import '../table.scss';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { EuiInMemoryTable } from '@elastic/eui';
|
||||
import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type';
|
||||
import { getFieldIconType } from '@kbn/field-utils/src/utils/get_field_icon_type';
|
||||
import {
|
||||
SHOW_MULTIFIELDS,
|
||||
formatFieldValue,
|
||||
|
|
|
@ -29,7 +29,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { debounce } from 'lodash';
|
||||
import { Storage } from '@kbn/kibana-utils-plugin/public';
|
||||
import { getFieldIconType } from '@kbn/unified-field-list/src/utils/field_types/get_field_icon_type';
|
||||
import { getFieldIconType } from '@kbn/field-utils/src/utils/get_field_icon_type';
|
||||
import {
|
||||
SHOW_MULTIFIELDS,
|
||||
formatFieldValue,
|
||||
|
@ -105,6 +105,7 @@ const updateSearchText = debounce(
|
|||
|
||||
export const DocViewerTable = ({
|
||||
columns,
|
||||
columnTypes,
|
||||
hit,
|
||||
dataView,
|
||||
filter,
|
||||
|
@ -165,7 +166,9 @@ export const DocViewerTable = ({
|
|||
(field: string) => {
|
||||
const fieldMapping = mapping(field);
|
||||
const displayName = fieldMapping?.displayName ?? field;
|
||||
const fieldType = isNestedFieldParent(field, dataView)
|
||||
const fieldType = columnTypes
|
||||
? columnTypes[field] // for text-based results types come separately
|
||||
: isNestedFieldParent(field, dataView)
|
||||
? 'nested'
|
||||
: fieldMapping
|
||||
? getFieldIconType(fieldMapping)
|
||||
|
@ -208,6 +211,7 @@ export const DocViewerTable = ({
|
|||
onToggleColumn,
|
||||
filter,
|
||||
columns,
|
||||
columnTypes,
|
||||
flattened,
|
||||
pinnedFields,
|
||||
onTogglePinned,
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
"@kbn/i18n-react",
|
||||
"@kbn/i18n",
|
||||
"@kbn/unified-doc-viewer",
|
||||
"@kbn/unified-field-list",
|
||||
"@kbn/kibana-utils-plugin",
|
||||
"@kbn/data-plugin",
|
||||
"@kbn/core-analytics-browser",
|
||||
|
@ -23,7 +22,8 @@
|
|||
"@kbn/core",
|
||||
"@kbn/shared-ux-utility",
|
||||
"@kbn/core-analytics-browser-mocks",
|
||||
"@kbn/core-ui-settings-browser-mocks"
|
||||
"@kbn/core-ui-settings-browser-mocks",
|
||||
"@kbn/field-utils"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
184
test/functional/apps/discover/group2/_data_grid_field_tokens.ts
Normal file
184
test/functional/apps/discover/group2/_data_grid_field_tokens.ts
Normal file
|
@ -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.
|
||||
*/
|
||||
|
||||
import expect from '@kbn/expect';
|
||||
import { WebElementWrapper } from '../../../services/lib/web_element_wrapper';
|
||||
import { FtrProviderContext } from '../ftr_provider_context';
|
||||
|
||||
export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
||||
const dataGrid = getService('dataGrid');
|
||||
const PageObjects = getPageObjects([
|
||||
'common',
|
||||
'discover',
|
||||
'timePicker',
|
||||
'dashboard',
|
||||
'unifiedFieldList',
|
||||
'header',
|
||||
]);
|
||||
const esArchiver = getService('esArchiver');
|
||||
const dashboardAddPanel = getService('dashboardAddPanel');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const kibanaServer = getService('kibanaServer');
|
||||
const security = getService('security');
|
||||
const defaultSettings = {
|
||||
defaultIndex: 'logstash-*',
|
||||
hideAnnouncements: true,
|
||||
};
|
||||
|
||||
async function findFirstColumnTokens() {
|
||||
const header = await testSubjects.find('euiDataGridBody > dataGridHeader');
|
||||
return await findFirstFieldIcons(header);
|
||||
}
|
||||
|
||||
async function findFirstDocViewerTokens() {
|
||||
await dataGrid.clickRowToggle({ rowIndex: 0 });
|
||||
const docViewer = await testSubjects.find('docTableDetailsFlyout');
|
||||
return await findFirstFieldIcons(docViewer);
|
||||
}
|
||||
|
||||
async function findFirstFieldIcons(element: WebElementWrapper) {
|
||||
const fieldIcons = await element.findAllByCssSelector('.kbnFieldIcon svg');
|
||||
|
||||
return await Promise.all(
|
||||
fieldIcons.map((fieldIcon) => fieldIcon.getAttribute('aria-label')).slice(0, 10)
|
||||
);
|
||||
}
|
||||
|
||||
describe('discover data grid field tokens', function () {
|
||||
before(async () => {
|
||||
await security.testUser.setRoles(['kibana_admin', 'test_logstash_reader']);
|
||||
await esArchiver.loadIfNeeded('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await kibanaServer.importExport.load('test/functional/fixtures/kbn_archiver/discover');
|
||||
});
|
||||
|
||||
after(async () => {
|
||||
await kibanaServer.importExport.unload('test/functional/fixtures/kbn_archiver/discover');
|
||||
await esArchiver.unload('test/functional/fixtures/es_archiver/logstash_functional');
|
||||
await kibanaServer.savedObjects.cleanStandardList();
|
||||
});
|
||||
|
||||
beforeEach(async function () {
|
||||
await PageObjects.timePicker.setDefaultAbsoluteRangeViaUiSettings();
|
||||
await kibanaServer.uiSettings.update(defaultSettings);
|
||||
await PageObjects.common.navigateToApp('discover');
|
||||
await PageObjects.discover.waitUntilSearchingHasFinished();
|
||||
});
|
||||
|
||||
it('should not render field tokens when Document column is visible', async function () {
|
||||
expect(await PageObjects.discover.getHitCount()).to.be('14,004');
|
||||
|
||||
expect(await findFirstColumnTokens()).to.eql([]);
|
||||
|
||||
expect(await findFirstDocViewerTokens()).to.eql([
|
||||
'Keyword',
|
||||
'Keyword',
|
||||
'Number',
|
||||
'Text',
|
||||
'Text',
|
||||
'Date',
|
||||
'Text',
|
||||
'Number',
|
||||
'IP address',
|
||||
'Text',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render field tokens correctly when columns are selected', async function () {
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('ip');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('geo.coordinates');
|
||||
|
||||
expect(await findFirstColumnTokens()).to.eql(['Number', 'Text', 'IP address', 'Geo point']);
|
||||
|
||||
expect(await findFirstDocViewerTokens()).to.eql([
|
||||
'Keyword',
|
||||
'Keyword',
|
||||
'Number',
|
||||
'Text',
|
||||
'Text',
|
||||
'Date',
|
||||
'Text',
|
||||
'Number',
|
||||
'IP address',
|
||||
'Text',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render field tokens correctly for ES|QL', async function () {
|
||||
await PageObjects.discover.selectTextBaseLang();
|
||||
expect(await PageObjects.discover.getHitCount()).to.be('10');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('@timestamp');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('ip');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('geo.coordinates');
|
||||
|
||||
expect(await findFirstColumnTokens()).to.eql(['Number', 'String', 'String']);
|
||||
|
||||
expect(await findFirstDocViewerTokens()).to.eql([
|
||||
'String',
|
||||
'String',
|
||||
'Date',
|
||||
'String',
|
||||
'Number',
|
||||
'String',
|
||||
'String',
|
||||
'Unknown field',
|
||||
'String',
|
||||
'String',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render field tokens correctly on Dashboard', async function () {
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('geo.coordinates');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd(
|
||||
'relatedContent.article:modified_time'
|
||||
);
|
||||
await PageObjects.discover.saveSearch('With columns');
|
||||
|
||||
await PageObjects.common.navigateToApp('dashboard');
|
||||
await PageObjects.dashboard.clickNewDashboard();
|
||||
await dashboardAddPanel.clickOpenAddPanel();
|
||||
await dashboardAddPanel.addSavedSearch('With columns');
|
||||
|
||||
expect(await findFirstColumnTokens()).to.eql(['Number', 'Text', 'Geo point', 'Date']);
|
||||
|
||||
expect(await findFirstDocViewerTokens()).to.eql([
|
||||
'Keyword',
|
||||
'Keyword',
|
||||
'Number',
|
||||
'Text',
|
||||
'Text',
|
||||
'Date',
|
||||
'Text',
|
||||
'Number',
|
||||
'IP address',
|
||||
'Text',
|
||||
]);
|
||||
});
|
||||
|
||||
it('should render field tokens correctly on Surrounding Documents page', async function () {
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('bytes');
|
||||
await PageObjects.unifiedFieldList.clickFieldListItemAdd('extension');
|
||||
|
||||
// navigate to the context view
|
||||
await dataGrid.clickRowToggle({ rowIndex: 0 });
|
||||
const [, surroundingActionEl] = await dataGrid.getRowActions({
|
||||
isAnchorRow: false,
|
||||
rowIndex: 0,
|
||||
});
|
||||
await surroundingActionEl.click();
|
||||
await PageObjects.header.waitUntilLoadingHasFinished();
|
||||
|
||||
expect(await findFirstColumnTokens()).to.eql(['Number', 'Text']);
|
||||
});
|
||||
});
|
||||
}
|
|
@ -32,6 +32,7 @@ export default function ({ getService, loadTestFile }: FtrProviderContext) {
|
|||
loadTestFile(require.resolve('./_data_grid_row_height'));
|
||||
loadTestFile(require.resolve('./_data_grid_pagination'));
|
||||
loadTestFile(require.resolve('./_data_grid_footer'));
|
||||
loadTestFile(require.resolve('./_data_grid_field_tokens'));
|
||||
loadTestFile(require.resolve('./_adhoc_data_views'));
|
||||
loadTestFile(require.resolve('./_esql_view'));
|
||||
loadTestFile(require.resolve('./_indexpattern_with_unmapped_fields'));
|
||||
|
|
|
@ -268,8 +268,8 @@ export class DataGridService extends FtrService {
|
|||
|
||||
const textArr = [];
|
||||
for (const cell of result) {
|
||||
const textContent = await cell.getAttribute('textContent');
|
||||
textArr.push(textContent.trim());
|
||||
const cellText = await cell.getVisibleText();
|
||||
textArr.push(cellText.trim());
|
||||
}
|
||||
return Promise.resolve(textArr);
|
||||
}
|
||||
|
|
|
@ -786,6 +786,8 @@
|
|||
"@kbn/field-formats-plugin/*": ["src/plugins/field_formats/*"],
|
||||
"@kbn/field-types": ["packages/kbn-field-types"],
|
||||
"@kbn/field-types/*": ["packages/kbn-field-types/*"],
|
||||
"@kbn/field-utils": ["packages/kbn-field-utils"],
|
||||
"@kbn/field-utils/*": ["packages/kbn-field-utils/*"],
|
||||
"@kbn/file-upload-plugin": ["x-pack/plugins/file_upload"],
|
||||
"@kbn/file-upload-plugin/*": ["x-pack/plugins/file_upload/*"],
|
||||
"@kbn/files-example-plugin": ["examples/files_example"],
|
||||
|
|
|
@ -9,7 +9,7 @@ import React, { FC } from 'react';
|
|||
import { EuiToolTip } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { FieldIcon } from '@kbn/react-field';
|
||||
import { getFieldTypeName } from '@kbn/discover-utils';
|
||||
import { getFieldTypeName } from '@kbn/field-utils';
|
||||
import './_index.scss';
|
||||
|
||||
interface FieldTypeIconProps {
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
import React, { FC, useMemo } from 'react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { getFieldTypeName } from '@kbn/discover-utils';
|
||||
import { getFieldTypeName } from '@kbn/field-utils';
|
||||
import { FieldTypesHelpPopover } from './field_types_help_popover';
|
||||
import { MultiSelectPicker, Option } from '../multi_select_picker';
|
||||
import type {
|
||||
|
|
|
@ -22,7 +22,7 @@ import React, { FC, useMemo, useState } from 'react';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { FieldIcon } from '@kbn/react-field';
|
||||
import { FormattedMessage } from '@kbn/i18n-react';
|
||||
import { getFieldTypeDescription } from '@kbn/unified-field-list/src/utils/field_types/get_field_type_description';
|
||||
import { getFieldTypeDescription } from '@kbn/field-utils/src/utils/get_field_type_description';
|
||||
import { useDataVisualizerKibana } from '../../../kibana_context';
|
||||
|
||||
interface FieldTypeTableItem {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
import { DataViewField } from '@kbn/data-views-plugin/public';
|
||||
import { KBN_FIELD_TYPES } from '@kbn/field-types';
|
||||
import { getFieldType } from '@kbn/unified-field-list/src/utils/field_types/get_field_type';
|
||||
import { getFieldType } from '@kbn/field-utils/src/utils/get_field_type';
|
||||
import { SUPPORTED_FIELD_TYPES } from '../../../../common/constants';
|
||||
|
||||
// convert kibana types to ML Job types
|
||||
|
|
|
@ -9,7 +9,7 @@ import React, { FC, useMemo } from 'react';
|
|||
import { EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { css } from '@emotion/react';
|
||||
import { getFieldTypeName } from '@kbn/discover-utils';
|
||||
import { getFieldTypeName } from '@kbn/field-utils';
|
||||
import { useCurrentEuiTheme } from '../../../common/hooks/use_current_eui_theme';
|
||||
import { FieldTypesHelpPopover } from '../../../common/components/field_types_filter/field_types_help_popover';
|
||||
import { FieldTypeIcon } from '../../../common/components/field_type_icon';
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
"@kbn/data-views-plugin",
|
||||
"@kbn/datemath",
|
||||
"@kbn/discover-plugin",
|
||||
"@kbn/discover-utils",
|
||||
"@kbn/embeddable-plugin",
|
||||
"@kbn/embeddable-plugin",
|
||||
"@kbn/es-query",
|
||||
|
@ -63,13 +62,13 @@
|
|||
"@kbn/unified-search-plugin",
|
||||
"@kbn/usage-collection-plugin",
|
||||
"@kbn/utility-types",
|
||||
"@kbn/unified-field-list",
|
||||
"@kbn/ml-string-hash",
|
||||
"@kbn/ml-random-sampler-utils",
|
||||
"@kbn/data-service",
|
||||
"@kbn/core-notifications-browser",
|
||||
"@kbn/ebt-tools",
|
||||
"@kbn/ml-chi2test"
|
||||
"@kbn/ml-chi2test",
|
||||
"@kbn/field-utils"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -24,7 +24,8 @@ import { dataViewPluginMocks } from '@kbn/data-views-plugin/public/mocks';
|
|||
import { DataView, DataViewField } from '@kbn/data-views-plugin/common';
|
||||
import { loadFieldStats } from '@kbn/unified-field-list/src/services/field_stats';
|
||||
import { DOCUMENT_FIELD_NAME } from '../../../common/constants';
|
||||
import { FieldIcon, FieldStats, FieldPopoverFooter } from '@kbn/unified-field-list';
|
||||
import { FieldIcon } from '@kbn/field-utils';
|
||||
import { FieldStats, FieldPopoverFooter } from '@kbn/unified-field-list';
|
||||
|
||||
jest.mock('@kbn/unified-field-list/src/services/field_stats', () => ({
|
||||
loadFieldStats: jest.fn().mockResolvedValue({}),
|
||||
|
|
|
@ -12,7 +12,7 @@ import { i18n } from '@kbn/i18n';
|
|||
import { EuiComboBoxOptionOption, EuiComboBoxProps } from '@elastic/eui';
|
||||
import { useExistingFieldsReader } from '@kbn/unified-field-list/src/hooks/use_existing_fields';
|
||||
import { FieldOption, FieldOptionValue, FieldPicker } from '@kbn/visualization-ui-components';
|
||||
import { getFieldIconType } from '@kbn/unified-field-list';
|
||||
import { getFieldIconType } from '@kbn/field-utils';
|
||||
import type { OperationType } from '../form_based';
|
||||
import type { OperationSupportMatrix } from './operation_support';
|
||||
import { fieldContainsData } from '../../../shared_components';
|
||||
|
|
|
@ -90,6 +90,7 @@
|
|||
"@kbn/search-response-warnings",
|
||||
"@kbn/logging",
|
||||
"@kbn/core-plugins-server",
|
||||
"@kbn/field-utils"
|
||||
],
|
||||
"exclude": [
|
||||
"target/**/*",
|
||||
|
|
|
@ -2398,34 +2398,34 @@
|
|||
"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",
|
||||
"discover.fieldNameIcons.binaryAriaLabel": "Binaire",
|
||||
"discover.fieldNameIcons.booleanAriaLabel": "Booléen",
|
||||
"discover.fieldNameIcons.conflictFieldAriaLabel": "Conflit",
|
||||
"discover.fieldNameIcons.counterFieldAriaLabel": "Indicateur de compteur",
|
||||
"discover.fieldNameIcons.dateFieldAriaLabel": "Date",
|
||||
"discover.fieldNameIcons.dateRangeFieldAriaLabel": "Plage de dates",
|
||||
"discover.fieldNameIcons.denseVectorFieldAriaLabel": "Vecteur dense",
|
||||
"discover.fieldNameIcons.flattenedFieldAriaLabel": "Lissé",
|
||||
"discover.fieldNameIcons.gaugeFieldAriaLabel": "Indicateur de jauge",
|
||||
"discover.fieldNameIcons.geoPointFieldAriaLabel": "Point géographique",
|
||||
"discover.fieldNameIcons.geoShapeFieldAriaLabel": "Forme géométrique",
|
||||
"discover.fieldNameIcons.histogramFieldAriaLabel": "Histogramme",
|
||||
"discover.fieldNameIcons.ipAddressFieldAriaLabel": "Adresse IP",
|
||||
"discover.fieldNameIcons.ipRangeFieldAriaLabel": "Plage d'IP",
|
||||
"discover.fieldNameIcons.keywordFieldAriaLabel": "Mot-clé",
|
||||
"discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"discover.fieldNameIcons.nestedFieldAriaLabel": "Imbriqué",
|
||||
"discover.fieldNameIcons.numberFieldAriaLabel": "Nombre",
|
||||
"discover.fieldNameIcons.pointFieldAriaLabel": "Point",
|
||||
"discover.fieldNameIcons.rankFeatureFieldAriaLabel": "Fonctionnalité de rang",
|
||||
"discover.fieldNameIcons.rankFeaturesFieldAriaLabel": "Fonctionnalités de rang",
|
||||
"discover.fieldNameIcons.recordAriaLabel": "Enregistrements",
|
||||
"discover.fieldNameIcons.shapeFieldAriaLabel": "Forme",
|
||||
"discover.fieldNameIcons.sourceFieldAriaLabel": "Champ source",
|
||||
"discover.fieldNameIcons.stringFieldAriaLabel": "Chaîne",
|
||||
"discover.fieldNameIcons.textFieldAriaLabel": "Texte",
|
||||
"discover.fieldNameIcons.unknownFieldAriaLabel": "Champ inconnu",
|
||||
"discover.fieldNameIcons.versionFieldAriaLabel": "Version",
|
||||
"fieldUtils.fieldNameIcons.binaryAriaLabel": "Binaire",
|
||||
"fieldUtils.fieldNameIcons.booleanAriaLabel": "Booléen",
|
||||
"fieldUtils.fieldNameIcons.conflictFieldAriaLabel": "Conflit",
|
||||
"fieldUtils.fieldNameIcons.counterFieldAriaLabel": "Indicateur de compteur",
|
||||
"fieldUtils.fieldNameIcons.dateFieldAriaLabel": "Date",
|
||||
"fieldUtils.fieldNameIcons.dateRangeFieldAriaLabel": "Plage de dates",
|
||||
"fieldUtils.fieldNameIcons.denseVectorFieldAriaLabel": "Vecteur dense",
|
||||
"fieldUtils.fieldNameIcons.flattenedFieldAriaLabel": "Lissé",
|
||||
"fieldUtils.fieldNameIcons.gaugeFieldAriaLabel": "Indicateur de jauge",
|
||||
"fieldUtils.fieldNameIcons.geoPointFieldAriaLabel": "Point géographique",
|
||||
"fieldUtils.fieldNameIcons.geoShapeFieldAriaLabel": "Forme géométrique",
|
||||
"fieldUtils.fieldNameIcons.histogramFieldAriaLabel": "Histogramme",
|
||||
"fieldUtils.fieldNameIcons.ipAddressFieldAriaLabel": "Adresse IP",
|
||||
"fieldUtils.fieldNameIcons.ipRangeFieldAriaLabel": "Plage d'IP",
|
||||
"fieldUtils.fieldNameIcons.keywordFieldAriaLabel": "Mot-clé",
|
||||
"fieldUtils.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"fieldUtils.fieldNameIcons.nestedFieldAriaLabel": "Imbriqué",
|
||||
"fieldUtils.fieldNameIcons.numberFieldAriaLabel": "Nombre",
|
||||
"fieldUtils.fieldNameIcons.pointFieldAriaLabel": "Point",
|
||||
"fieldUtils.fieldNameIcons.rankFeatureFieldAriaLabel": "Fonctionnalité de rang",
|
||||
"fieldUtils.fieldNameIcons.rankFeaturesFieldAriaLabel": "Fonctionnalités de rang",
|
||||
"fieldUtils.fieldNameIcons.recordAriaLabel": "Enregistrements",
|
||||
"fieldUtils.fieldNameIcons.shapeFieldAriaLabel": "Forme",
|
||||
"fieldUtils.fieldNameIcons.sourceFieldAriaLabel": "Champ source",
|
||||
"fieldUtils.fieldNameIcons.stringFieldAriaLabel": "Chaîne",
|
||||
"fieldUtils.fieldNameIcons.textFieldAriaLabel": "Texte",
|
||||
"fieldUtils.fieldNameIcons.unknownFieldAriaLabel": "Champ inconnu",
|
||||
"fieldUtils.fieldNameIcons.versionFieldAriaLabel": "Version",
|
||||
"unifiedDocViewer.docView.table.actions.label": "Actions",
|
||||
"unifiedDocViewer.docView.table.actions.open": "Actions ouvertes",
|
||||
"unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "Une ou plusieurs valeurs dans ce champ sont trop longues et ne peuvent pas être recherchées ni filtrées.",
|
||||
|
@ -5645,33 +5645,33 @@
|
|||
"unifiedFieldList.fieldList.noFieldsCallout.noFields.tryText": "Essayer :",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFieldsLabel": "Aucun champ n'existe dans cette vue de données.",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFilteredFieldsLabel": "Aucun champ ne correspond aux filtres sélectionnés.",
|
||||
"unifiedFieldList.fieldNameDescription.binaryField": "Valeur binaire encodée en tant que chaîne Base64.",
|
||||
"unifiedFieldList.fieldNameDescription.booleanField": "Valeurs vraies ou fausses.",
|
||||
"unifiedFieldList.fieldNameDescription.conflictField": "Le champ possède des valeurs de différents types. Corrigez le problème dans Gestion > Vues de données.",
|
||||
"unifiedFieldList.fieldNameDescription.counterField": "Nombre qui ne peut qu'augmenter ou être réinitialisé sur 0 (zéro). Disponible uniquement pour les champs numériques et aggregate_metric_double.",
|
||||
"unifiedFieldList.fieldNameDescription.dateField": "Chaîne de date ou nombre de secondes ou de millisecondes depuis 1/1/1970.",
|
||||
"unifiedFieldList.fieldNameDescription.dateRangeField": "Plage de valeurs de date.",
|
||||
"unifiedFieldList.fieldNameDescription.denseVectorField": "Enregistre les vecteurs denses des valeurs Éléments flottants.",
|
||||
"unifiedFieldList.fieldNameDescription.flattenedField": "Objet JSON tout entier en tant que valeur de champ unique.",
|
||||
"unifiedFieldList.fieldNameDescription.gaugeField": "Nombre qui peut augmenter ou diminuer. Disponible uniquement pour les champs numériques et aggregate_metric_double.",
|
||||
"unifiedFieldList.fieldNameDescription.geoPointField": "Points de latitude et de longitude.",
|
||||
"unifiedFieldList.fieldNameDescription.geoShapeField": "Formes complexes, telles que des polygones.",
|
||||
"unifiedFieldList.fieldNameDescription.histogramField": "Valeurs numériques pré-agrégées sous forme d'histogramme.",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressField": "Adresses IPv4 et IPv6.",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressRangeField": "Plage de valeurs IP prenant en charge les adresses IPv4 ou IPv6 (ou les 2).",
|
||||
"unifiedFieldList.fieldNameDescription.keywordField": "Contenu structuré tel qu'un ID, une adresse e-mail, un nom d'hôte, un code de statut, ou une balise.",
|
||||
"unifiedFieldList.fieldNameDescription.murmur3Field": "Champ qui calcule et stocke les hachages de valeurs.",
|
||||
"unifiedFieldList.fieldNameDescription.nestedField": "Objet JSON qui conserve la relation entre ses sous-champs.",
|
||||
"unifiedFieldList.fieldNameDescription.numberField": "Valeurs Long, Entier, Court, Octet, Double et Élément flottant.",
|
||||
"unifiedFieldList.fieldNameDescription.pointField": "Points cartésiens arbitraires.",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeatureField": "Enregistre une fonctionnalité numérique pour augmenter le nombre de résultats au moment de la requête.",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeaturesField": "Enregistre des fonctionnalités numériques pour augmenter le nombre de résultats au moment de la requête.",
|
||||
"unifiedFieldList.fieldNameDescription.recordField": "Nombre d'enregistrements.",
|
||||
"unifiedFieldList.fieldNameDescription.shapeField": "Géométries cartésiennes arbitraires.",
|
||||
"unifiedFieldList.fieldNameDescription.stringField": "Texte intégral tel que le corps d'un e-mail ou la description d'un produit.",
|
||||
"unifiedFieldList.fieldNameDescription.textField": "Texte intégral tel que le corps d'un e-mail ou la description d'un produit.",
|
||||
"unifiedFieldList.fieldNameDescription.unknownField": "Champ inconnu",
|
||||
"unifiedFieldList.fieldNameDescription.versionField": "Versions des logiciels. Prend en charge les règles de priorité de la Gestion sémantique des versions.",
|
||||
"fieldUtils.fieldNameDescription.binaryField": "Valeur binaire encodée en tant que chaîne Base64.",
|
||||
"fieldUtils.fieldNameDescription.booleanField": "Valeurs vraies ou fausses.",
|
||||
"fieldUtils.fieldNameDescription.conflictField": "Le champ possède des valeurs de différents types. Corrigez le problème dans Gestion > Vues de données.",
|
||||
"fieldUtils.fieldNameDescription.counterField": "Nombre qui ne peut qu'augmenter ou être réinitialisé sur 0 (zéro). Disponible uniquement pour les champs numériques et aggregate_metric_double.",
|
||||
"fieldUtils.fieldNameDescription.dateField": "Chaîne de date ou nombre de secondes ou de millisecondes depuis 1/1/1970.",
|
||||
"fieldUtils.fieldNameDescription.dateRangeField": "Plage de valeurs de date.",
|
||||
"fieldUtils.fieldNameDescription.denseVectorField": "Enregistre les vecteurs denses des valeurs Éléments flottants.",
|
||||
"fieldUtils.fieldNameDescription.flattenedField": "Objet JSON tout entier en tant que valeur de champ unique.",
|
||||
"fieldUtils.fieldNameDescription.gaugeField": "Nombre qui peut augmenter ou diminuer. Disponible uniquement pour les champs numériques et aggregate_metric_double.",
|
||||
"fieldUtils.fieldNameDescription.geoPointField": "Points de latitude et de longitude.",
|
||||
"fieldUtils.fieldNameDescription.geoShapeField": "Formes complexes, telles que des polygones.",
|
||||
"fieldUtils.fieldNameDescription.histogramField": "Valeurs numériques pré-agrégées sous forme d'histogramme.",
|
||||
"fieldUtils.fieldNameDescription.ipAddressField": "Adresses IPv4 et IPv6.",
|
||||
"fieldUtils.fieldNameDescription.ipAddressRangeField": "Plage de valeurs IP prenant en charge les adresses IPv4 ou IPv6 (ou les 2).",
|
||||
"fieldUtils.fieldNameDescription.keywordField": "Contenu structuré tel qu'un ID, une adresse e-mail, un nom d'hôte, un code de statut, ou une balise.",
|
||||
"fieldUtils.fieldNameDescription.murmur3Field": "Champ qui calcule et stocke les hachages de valeurs.",
|
||||
"fieldUtils.fieldNameDescription.nestedField": "Objet JSON qui conserve la relation entre ses sous-champs.",
|
||||
"fieldUtils.fieldNameDescription.numberField": "Valeurs Long, Entier, Court, Octet, Double et Élément flottant.",
|
||||
"fieldUtils.fieldNameDescription.pointField": "Points cartésiens arbitraires.",
|
||||
"fieldUtils.fieldNameDescription.rankFeatureField": "Enregistre une fonctionnalité numérique pour augmenter le nombre de résultats au moment de la requête.",
|
||||
"fieldUtils.fieldNameDescription.rankFeaturesField": "Enregistre des fonctionnalités numériques pour augmenter le nombre de résultats au moment de la requête.",
|
||||
"fieldUtils.fieldNameDescription.recordField": "Nombre d'enregistrements.",
|
||||
"fieldUtils.fieldNameDescription.shapeField": "Géométries cartésiennes arbitraires.",
|
||||
"fieldUtils.fieldNameDescription.stringField": "Texte intégral tel que le corps d'un e-mail ou la description d'un produit.",
|
||||
"fieldUtils.fieldNameDescription.textField": "Texte intégral tel que le corps d'un e-mail ou la description d'un produit.",
|
||||
"fieldUtils.fieldNameDescription.unknownField": "Champ inconnu",
|
||||
"fieldUtils.fieldNameDescription.versionField": "Versions des logiciels. Prend en charge les règles de priorité de la Gestion sémantique des versions.",
|
||||
"unifiedFieldList.fieldNameSearch.filterByNameLabel": "Rechercher les noms de champs",
|
||||
"unifiedFieldList.fieldPopover.addExistsFilterLabel": "Filtrer sur le champ",
|
||||
"unifiedFieldList.fieldPopover.deleteFieldLabel": "Supprimer le champ de la vue de données",
|
||||
|
|
|
@ -2413,34 +2413,34 @@
|
|||
"discover.viewAlert.searchSourceErrorTitle": "検索ソースの取得エラー",
|
||||
"discover.viewModes.document.label": "ドキュメント",
|
||||
"discover.viewModes.fieldStatistics.label": "フィールド統計情報",
|
||||
"discover.fieldNameIcons.binaryAriaLabel": "バイナリー",
|
||||
"discover.fieldNameIcons.booleanAriaLabel": "ブール",
|
||||
"discover.fieldNameIcons.conflictFieldAriaLabel": "競合",
|
||||
"discover.fieldNameIcons.counterFieldAriaLabel": "カウンターメトリック",
|
||||
"discover.fieldNameIcons.dateFieldAriaLabel": "日付",
|
||||
"discover.fieldNameIcons.dateRangeFieldAriaLabel": "日付範囲",
|
||||
"discover.fieldNameIcons.denseVectorFieldAriaLabel": "密集ベクトル",
|
||||
"discover.fieldNameIcons.flattenedFieldAriaLabel": "平坦化済み",
|
||||
"discover.fieldNameIcons.gaugeFieldAriaLabel": "ゲージメトリック",
|
||||
"discover.fieldNameIcons.geoPointFieldAriaLabel": "地理ポイント",
|
||||
"discover.fieldNameIcons.geoShapeFieldAriaLabel": "地理情報図形",
|
||||
"discover.fieldNameIcons.histogramFieldAriaLabel": "ヒストグラム",
|
||||
"discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP アドレス",
|
||||
"discover.fieldNameIcons.ipRangeFieldAriaLabel": "IP範囲",
|
||||
"discover.fieldNameIcons.keywordFieldAriaLabel": "キーワード",
|
||||
"discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"discover.fieldNameIcons.nestedFieldAriaLabel": "ネスト済み",
|
||||
"discover.fieldNameIcons.numberFieldAriaLabel": "数字",
|
||||
"discover.fieldNameIcons.pointFieldAriaLabel": "点",
|
||||
"discover.fieldNameIcons.rankFeatureFieldAriaLabel": "ランク特性",
|
||||
"discover.fieldNameIcons.rankFeaturesFieldAriaLabel": "ランク特性",
|
||||
"discover.fieldNameIcons.recordAriaLabel": "記録",
|
||||
"discover.fieldNameIcons.shapeFieldAriaLabel": "形状",
|
||||
"discover.fieldNameIcons.sourceFieldAriaLabel": "ソースフィールド",
|
||||
"discover.fieldNameIcons.stringFieldAriaLabel": "文字列",
|
||||
"discover.fieldNameIcons.textFieldAriaLabel": "テキスト",
|
||||
"discover.fieldNameIcons.unknownFieldAriaLabel": "不明なフィールド",
|
||||
"discover.fieldNameIcons.versionFieldAriaLabel": "バージョン",
|
||||
"fieldUtils.fieldNameIcons.binaryAriaLabel": "バイナリー",
|
||||
"fieldUtils.fieldNameIcons.booleanAriaLabel": "ブール",
|
||||
"fieldUtils.fieldNameIcons.conflictFieldAriaLabel": "競合",
|
||||
"fieldUtils.fieldNameIcons.counterFieldAriaLabel": "カウンターメトリック",
|
||||
"fieldUtils.fieldNameIcons.dateFieldAriaLabel": "日付",
|
||||
"fieldUtils.fieldNameIcons.dateRangeFieldAriaLabel": "日付範囲",
|
||||
"fieldUtils.fieldNameIcons.denseVectorFieldAriaLabel": "密集ベクトル",
|
||||
"fieldUtils.fieldNameIcons.flattenedFieldAriaLabel": "平坦化済み",
|
||||
"fieldUtils.fieldNameIcons.gaugeFieldAriaLabel": "ゲージメトリック",
|
||||
"fieldUtils.fieldNameIcons.geoPointFieldAriaLabel": "地理ポイント",
|
||||
"fieldUtils.fieldNameIcons.geoShapeFieldAriaLabel": "地理情報図形",
|
||||
"fieldUtils.fieldNameIcons.histogramFieldAriaLabel": "ヒストグラム",
|
||||
"fieldUtils.fieldNameIcons.ipAddressFieldAriaLabel": "IP アドレス",
|
||||
"fieldUtils.fieldNameIcons.ipRangeFieldAriaLabel": "IP範囲",
|
||||
"fieldUtils.fieldNameIcons.keywordFieldAriaLabel": "キーワード",
|
||||
"fieldUtils.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"fieldUtils.fieldNameIcons.nestedFieldAriaLabel": "ネスト済み",
|
||||
"fieldUtils.fieldNameIcons.numberFieldAriaLabel": "数字",
|
||||
"fieldUtils.fieldNameIcons.pointFieldAriaLabel": "点",
|
||||
"fieldUtils.fieldNameIcons.rankFeatureFieldAriaLabel": "ランク特性",
|
||||
"fieldUtils.fieldNameIcons.rankFeaturesFieldAriaLabel": "ランク特性",
|
||||
"fieldUtils.fieldNameIcons.recordAriaLabel": "記録",
|
||||
"fieldUtils.fieldNameIcons.shapeFieldAriaLabel": "形状",
|
||||
"fieldUtils.fieldNameIcons.sourceFieldAriaLabel": "ソースフィールド",
|
||||
"fieldUtils.fieldNameIcons.stringFieldAriaLabel": "文字列",
|
||||
"fieldUtils.fieldNameIcons.textFieldAriaLabel": "テキスト",
|
||||
"fieldUtils.fieldNameIcons.unknownFieldAriaLabel": "不明なフィールド",
|
||||
"fieldUtils.fieldNameIcons.versionFieldAriaLabel": "バージョン",
|
||||
"unifiedDocViewer.docView.table.actions.label": "アクション",
|
||||
"unifiedDocViewer.docView.table.actions.open": "アクションを開く",
|
||||
"unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "このフィールドの1つ以上の値が長すぎるため、検索またはフィルタリングできません。",
|
||||
|
@ -5661,33 +5661,33 @@
|
|||
"unifiedFieldList.fieldList.noFieldsCallout.noFields.tryText": "試行対象:",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFieldsLabel": "このデータビューにはフィールドがありません。",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFilteredFieldsLabel": "選択したフィルターと一致するフィールドはありません。",
|
||||
"unifiedFieldList.fieldNameDescription.binaryField": "Base64文字列としてエンコードされたバイナリ値",
|
||||
"unifiedFieldList.fieldNameDescription.booleanField": "True および False 値。",
|
||||
"unifiedFieldList.fieldNameDescription.conflictField": "フィールドには異なる型の値があります。[管理 > データビュー]で解決してください。",
|
||||
"unifiedFieldList.fieldNameDescription.counterField": "0(ゼロ)に増加またはリセットのみされる数値。数値およびaggregate_metric_doubleフィールドでのみ使用可能です。",
|
||||
"unifiedFieldList.fieldNameDescription.dateField": "日付文字列、または1/1/1970以降の秒またはミリ秒の数値。",
|
||||
"unifiedFieldList.fieldNameDescription.dateRangeField": "日付値の範囲。",
|
||||
"unifiedFieldList.fieldNameDescription.denseVectorField": "浮動小数点数値の密ベクトルを記録します。",
|
||||
"unifiedFieldList.fieldNameDescription.flattenedField": "1つのフィールド値としてのJSONオブジェクト全体。",
|
||||
"unifiedFieldList.fieldNameDescription.gaugeField": "増減可能な数値。数値およびaggregate_metric_doubleフィールドでのみ使用可能です。",
|
||||
"unifiedFieldList.fieldNameDescription.geoPointField": "緯度および経度点。",
|
||||
"unifiedFieldList.fieldNameDescription.geoShapeField": "多角形などの複雑な図形。",
|
||||
"unifiedFieldList.fieldNameDescription.histogramField": "ヒストグラムの形式の集計された数値。",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressField": "IPv4およびIPv6アドレス。",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressRangeField": "IPv4またはIPv6(または混合)のアドレスをサポートするIP値の範囲。",
|
||||
"unifiedFieldList.fieldNameDescription.keywordField": "ID、電子メールアドレス、ホスト名、ステータスコード、タグなどの構造化されたコンテンツ。",
|
||||
"unifiedFieldList.fieldNameDescription.murmur3Field": "値のハッシュタグを計算して格納するフィールド。",
|
||||
"unifiedFieldList.fieldNameDescription.nestedField": "サブフィールド間の関係を保持するJSONオブジェクト。",
|
||||
"unifiedFieldList.fieldNameDescription.numberField": "長整数、整数、短整数、バイト、倍精度浮動小数点数、浮動小数点数の値。",
|
||||
"unifiedFieldList.fieldNameDescription.pointField": "任意の直交点。",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeatureField": "クエリ時のヒット数を増やすために、数値機能を記録します。",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeaturesField": "クエリ時のヒット数を増やすために、数値機能を記録します。",
|
||||
"unifiedFieldList.fieldNameDescription.recordField": "レコード数。",
|
||||
"unifiedFieldList.fieldNameDescription.shapeField": "任意の解析幾何。",
|
||||
"unifiedFieldList.fieldNameDescription.stringField": "電子メール本文や製品説明などの全文テキスト。",
|
||||
"unifiedFieldList.fieldNameDescription.textField": "電子メール本文や製品説明などの全文テキスト。",
|
||||
"unifiedFieldList.fieldNameDescription.unknownField": "不明なフィールド",
|
||||
"unifiedFieldList.fieldNameDescription.versionField": "ソフトウェアバージョン。「セマンティックバージョニング」優先度ルールをサポートします。",
|
||||
"fieldUtils.fieldNameDescription.binaryField": "Base64文字列としてエンコードされたバイナリ値",
|
||||
"fieldUtils.fieldNameDescription.booleanField": "True および False 値。",
|
||||
"fieldUtils.fieldNameDescription.conflictField": "フィールドには異なる型の値があります。[管理 > データビュー]で解決してください。",
|
||||
"fieldUtils.fieldNameDescription.counterField": "0(ゼロ)に増加またはリセットのみされる数値。数値およびaggregate_metric_doubleフィールドでのみ使用可能です。",
|
||||
"fieldUtils.fieldNameDescription.dateField": "日付文字列、または1/1/1970以降の秒またはミリ秒の数値。",
|
||||
"fieldUtils.fieldNameDescription.dateRangeField": "日付値の範囲。",
|
||||
"fieldUtils.fieldNameDescription.denseVectorField": "浮動小数点数値の密ベクトルを記録します。",
|
||||
"fieldUtils.fieldNameDescription.flattenedField": "1つのフィールド値としてのJSONオブジェクト全体。",
|
||||
"fieldUtils.fieldNameDescription.gaugeField": "増減可能な数値。数値およびaggregate_metric_doubleフィールドでのみ使用可能です。",
|
||||
"fieldUtils.fieldNameDescription.geoPointField": "緯度および経度点。",
|
||||
"fieldUtils.fieldNameDescription.geoShapeField": "多角形などの複雑な図形。",
|
||||
"fieldUtils.fieldNameDescription.histogramField": "ヒストグラムの形式の集計された数値。",
|
||||
"fieldUtils.fieldNameDescription.ipAddressField": "IPv4およびIPv6アドレス。",
|
||||
"fieldUtils.fieldNameDescription.ipAddressRangeField": "IPv4またはIPv6(または混合)のアドレスをサポートするIP値の範囲。",
|
||||
"fieldUtils.fieldNameDescription.keywordField": "ID、電子メールアドレス、ホスト名、ステータスコード、タグなどの構造化されたコンテンツ。",
|
||||
"fieldUtils.fieldNameDescription.murmur3Field": "値のハッシュタグを計算して格納するフィールド。",
|
||||
"fieldUtils.fieldNameDescription.nestedField": "サブフィールド間の関係を保持するJSONオブジェクト。",
|
||||
"fieldUtils.fieldNameDescription.numberField": "長整数、整数、短整数、バイト、倍精度浮動小数点数、浮動小数点数の値。",
|
||||
"fieldUtils.fieldNameDescription.pointField": "任意の直交点。",
|
||||
"fieldUtils.fieldNameDescription.rankFeatureField": "クエリ時のヒット数を増やすために、数値機能を記録します。",
|
||||
"fieldUtils.fieldNameDescription.rankFeaturesField": "クエリ時のヒット数を増やすために、数値機能を記録します。",
|
||||
"fieldUtils.fieldNameDescription.recordField": "レコード数。",
|
||||
"fieldUtils.fieldNameDescription.shapeField": "任意の解析幾何。",
|
||||
"fieldUtils.fieldNameDescription.stringField": "電子メール本文や製品説明などの全文テキスト。",
|
||||
"fieldUtils.fieldNameDescription.textField": "電子メール本文や製品説明などの全文テキスト。",
|
||||
"fieldUtils.fieldNameDescription.unknownField": "不明なフィールド",
|
||||
"fieldUtils.fieldNameDescription.versionField": "ソフトウェアバージョン。「セマンティックバージョニング」優先度ルールをサポートします。",
|
||||
"unifiedFieldList.fieldNameSearch.filterByNameLabel": "検索フィールド名",
|
||||
"unifiedFieldList.fieldPopover.addExistsFilterLabel": "フィールド表示のフィルター",
|
||||
"unifiedFieldList.fieldPopover.deleteFieldLabel": "データビューフィールドを削除",
|
||||
|
|
|
@ -2413,34 +2413,34 @@
|
|||
"discover.viewAlert.searchSourceErrorTitle": "提取搜索源时出错",
|
||||
"discover.viewModes.document.label": "文档",
|
||||
"discover.viewModes.fieldStatistics.label": "字段统计信息",
|
||||
"discover.fieldNameIcons.binaryAriaLabel": "二进制",
|
||||
"discover.fieldNameIcons.booleanAriaLabel": "布尔型",
|
||||
"discover.fieldNameIcons.conflictFieldAriaLabel": "冲突",
|
||||
"discover.fieldNameIcons.counterFieldAriaLabel": "计数器指标",
|
||||
"discover.fieldNameIcons.dateFieldAriaLabel": "日期",
|
||||
"discover.fieldNameIcons.dateRangeFieldAriaLabel": "日期范围",
|
||||
"discover.fieldNameIcons.denseVectorFieldAriaLabel": "密集向量",
|
||||
"discover.fieldNameIcons.flattenedFieldAriaLabel": "扁平",
|
||||
"discover.fieldNameIcons.gaugeFieldAriaLabel": "仪表盘指标",
|
||||
"discover.fieldNameIcons.geoPointFieldAriaLabel": "地理点",
|
||||
"discover.fieldNameIcons.geoShapeFieldAriaLabel": "几何形状",
|
||||
"discover.fieldNameIcons.histogramFieldAriaLabel": "直方图",
|
||||
"discover.fieldNameIcons.ipAddressFieldAriaLabel": "IP 地址",
|
||||
"discover.fieldNameIcons.ipRangeFieldAriaLabel": "IP 范围",
|
||||
"discover.fieldNameIcons.keywordFieldAriaLabel": "关键字",
|
||||
"discover.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"discover.fieldNameIcons.nestedFieldAriaLabel": "嵌套",
|
||||
"discover.fieldNameIcons.numberFieldAriaLabel": "数字",
|
||||
"discover.fieldNameIcons.pointFieldAriaLabel": "点",
|
||||
"discover.fieldNameIcons.rankFeatureFieldAriaLabel": "排名特征",
|
||||
"discover.fieldNameIcons.rankFeaturesFieldAriaLabel": "排名特征",
|
||||
"discover.fieldNameIcons.recordAriaLabel": "记录",
|
||||
"discover.fieldNameIcons.shapeFieldAriaLabel": "形状",
|
||||
"discover.fieldNameIcons.sourceFieldAriaLabel": "源字段",
|
||||
"discover.fieldNameIcons.stringFieldAriaLabel": "字符串",
|
||||
"discover.fieldNameIcons.textFieldAriaLabel": "文本",
|
||||
"discover.fieldNameIcons.unknownFieldAriaLabel": "未知字段",
|
||||
"discover.fieldNameIcons.versionFieldAriaLabel": "版本",
|
||||
"fieldUtils.fieldNameIcons.binaryAriaLabel": "二进制",
|
||||
"fieldUtils.fieldNameIcons.booleanAriaLabel": "布尔型",
|
||||
"fieldUtils.fieldNameIcons.conflictFieldAriaLabel": "冲突",
|
||||
"fieldUtils.fieldNameIcons.counterFieldAriaLabel": "计数器指标",
|
||||
"fieldUtils.fieldNameIcons.dateFieldAriaLabel": "日期",
|
||||
"fieldUtils.fieldNameIcons.dateRangeFieldAriaLabel": "日期范围",
|
||||
"fieldUtils.fieldNameIcons.denseVectorFieldAriaLabel": "密集向量",
|
||||
"fieldUtils.fieldNameIcons.flattenedFieldAriaLabel": "扁平",
|
||||
"fieldUtils.fieldNameIcons.gaugeFieldAriaLabel": "仪表盘指标",
|
||||
"fieldUtils.fieldNameIcons.geoPointFieldAriaLabel": "地理点",
|
||||
"fieldUtils.fieldNameIcons.geoShapeFieldAriaLabel": "几何形状",
|
||||
"fieldUtils.fieldNameIcons.histogramFieldAriaLabel": "直方图",
|
||||
"fieldUtils.fieldNameIcons.ipAddressFieldAriaLabel": "IP 地址",
|
||||
"fieldUtils.fieldNameIcons.ipRangeFieldAriaLabel": "IP 范围",
|
||||
"fieldUtils.fieldNameIcons.keywordFieldAriaLabel": "关键字",
|
||||
"fieldUtils.fieldNameIcons.murmur3FieldAriaLabel": "Murmur3",
|
||||
"fieldUtils.fieldNameIcons.nestedFieldAriaLabel": "嵌套",
|
||||
"fieldUtils.fieldNameIcons.numberFieldAriaLabel": "数字",
|
||||
"fieldUtils.fieldNameIcons.pointFieldAriaLabel": "点",
|
||||
"fieldUtils.fieldNameIcons.rankFeatureFieldAriaLabel": "排名特征",
|
||||
"fieldUtils.fieldNameIcons.rankFeaturesFieldAriaLabel": "排名特征",
|
||||
"fieldUtils.fieldNameIcons.recordAriaLabel": "记录",
|
||||
"fieldUtils.fieldNameIcons.shapeFieldAriaLabel": "形状",
|
||||
"fieldUtils.fieldNameIcons.sourceFieldAriaLabel": "源字段",
|
||||
"fieldUtils.fieldNameIcons.stringFieldAriaLabel": "字符串",
|
||||
"fieldUtils.fieldNameIcons.textFieldAriaLabel": "文本",
|
||||
"fieldUtils.fieldNameIcons.unknownFieldAriaLabel": "未知字段",
|
||||
"fieldUtils.fieldNameIcons.versionFieldAriaLabel": "版本",
|
||||
"unifiedDocViewer.docView.table.actions.label": "操作",
|
||||
"unifiedDocViewer.docView.table.actions.open": "打开操作",
|
||||
"unifiedDocViewer.docView.table.ignored.multiAboveTooltip": "此字段中的一个或多个值过长,无法搜索或筛选。",
|
||||
|
@ -5660,33 +5660,33 @@
|
|||
"unifiedFieldList.fieldList.noFieldsCallout.noFields.tryText": "尝试:",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFieldsLabel": "在此数据视图中不存在任何字段。",
|
||||
"unifiedFieldList.fieldList.noFieldsCallout.noFilteredFieldsLabel": "没有字段匹配选定筛选。",
|
||||
"unifiedFieldList.fieldNameDescription.binaryField": "编码为 Base64 字符串的二进制值。",
|
||||
"unifiedFieldList.fieldNameDescription.booleanField": "True 和 False 值。",
|
||||
"unifiedFieldList.fieldNameDescription.conflictField": "字体具有不同类型的值。在“管理”>“数据视图”中解析。",
|
||||
"unifiedFieldList.fieldNameDescription.counterField": "只会增大或重置为 0(零)的数字。仅适用于数字和 aggregate_metric_double 字段。",
|
||||
"unifiedFieldList.fieldNameDescription.dateField": "日期字符串或 1/1/1970 以来的秒数或毫秒数。",
|
||||
"unifiedFieldList.fieldNameDescription.dateRangeField": "日期值的范围。",
|
||||
"unifiedFieldList.fieldNameDescription.denseVectorField": "记录浮点值的密集向量。",
|
||||
"unifiedFieldList.fieldNameDescription.flattenedField": "整个 JSON 对象作为单一字段值。",
|
||||
"unifiedFieldList.fieldNameDescription.gaugeField": "可以增大或减小的数字。仅适用于数字和 aggregate_metric_double 字段。",
|
||||
"unifiedFieldList.fieldNameDescription.geoPointField": "纬度和经度点。",
|
||||
"unifiedFieldList.fieldNameDescription.geoShapeField": "复杂形状,如多边形。",
|
||||
"unifiedFieldList.fieldNameDescription.histogramField": "直方图形式的预聚合数字值。",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressField": "IPv4 和 IPv6 地址。",
|
||||
"unifiedFieldList.fieldNameDescription.ipAddressRangeField": "支持 IPv4 或 IPv6(或混合)地址的 IP 值的范围。",
|
||||
"unifiedFieldList.fieldNameDescription.keywordField": "结构化内容,如 ID、电子邮件地址、主机名、状态代码或标签。",
|
||||
"unifiedFieldList.fieldNameDescription.murmur3Field": "计算和存储值哈希的字段。",
|
||||
"unifiedFieldList.fieldNameDescription.nestedField": "保留其子字段之间关系的 JSON 对象。",
|
||||
"unifiedFieldList.fieldNameDescription.numberField": "长整型、整数、短整型、字节、双精度和浮点值。",
|
||||
"unifiedFieldList.fieldNameDescription.pointField": "任意笛卡尔点。",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeatureField": "记录数字特征以提高查询时的命中数。",
|
||||
"unifiedFieldList.fieldNameDescription.rankFeaturesField": "记录数字特征以提高查询时的命中数。",
|
||||
"unifiedFieldList.fieldNameDescription.recordField": "记录计数。",
|
||||
"unifiedFieldList.fieldNameDescription.shapeField": "任意笛卡尔几何形状。",
|
||||
"unifiedFieldList.fieldNameDescription.stringField": "全文本,如电子邮件正文或产品描述。",
|
||||
"unifiedFieldList.fieldNameDescription.textField": "全文本,如电子邮件正文或产品描述。",
|
||||
"unifiedFieldList.fieldNameDescription.unknownField": "未知字段",
|
||||
"unifiedFieldList.fieldNameDescription.versionField": "软件版本。支持“语义版本控制”优先规则。",
|
||||
"fieldUtils.fieldNameDescription.binaryField": "编码为 Base64 字符串的二进制值。",
|
||||
"fieldUtils.fieldNameDescription.booleanField": "True 和 False 值。",
|
||||
"fieldUtils.fieldNameDescription.conflictField": "字体具有不同类型的值。在“管理”>“数据视图”中解析。",
|
||||
"fieldUtils.fieldNameDescription.counterField": "只会增大或重置为 0(零)的数字。仅适用于数字和 aggregate_metric_double 字段。",
|
||||
"fieldUtils.fieldNameDescription.dateField": "日期字符串或 1/1/1970 以来的秒数或毫秒数。",
|
||||
"fieldUtils.fieldNameDescription.dateRangeField": "日期值的范围。",
|
||||
"fieldUtils.fieldNameDescription.denseVectorField": "记录浮点值的密集向量。",
|
||||
"fieldUtils.fieldNameDescription.flattenedField": "整个 JSON 对象作为单一字段值。",
|
||||
"fieldUtils.fieldNameDescription.gaugeField": "可以增大或减小的数字。仅适用于数字和 aggregate_metric_double 字段。",
|
||||
"fieldUtils.fieldNameDescription.geoPointField": "纬度和经度点。",
|
||||
"fieldUtils.fieldNameDescription.geoShapeField": "复杂形状,如多边形。",
|
||||
"fieldUtils.fieldNameDescription.histogramField": "直方图形式的预聚合数字值。",
|
||||
"fieldUtils.fieldNameDescription.ipAddressField": "IPv4 和 IPv6 地址。",
|
||||
"fieldUtils.fieldNameDescription.ipAddressRangeField": "支持 IPv4 或 IPv6(或混合)地址的 IP 值的范围。",
|
||||
"fieldUtils.fieldNameDescription.keywordField": "结构化内容,如 ID、电子邮件地址、主机名、状态代码或标签。",
|
||||
"fieldUtils.fieldNameDescription.murmur3Field": "计算和存储值哈希的字段。",
|
||||
"fieldUtils.fieldNameDescription.nestedField": "保留其子字段之间关系的 JSON 对象。",
|
||||
"fieldUtils.fieldNameDescription.numberField": "长整型、整数、短整型、字节、双精度和浮点值。",
|
||||
"fieldUtils.fieldNameDescription.pointField": "任意笛卡尔点。",
|
||||
"fieldUtils.fieldNameDescription.rankFeatureField": "记录数字特征以提高查询时的命中数。",
|
||||
"fieldUtils.fieldNameDescription.rankFeaturesField": "记录数字特征以提高查询时的命中数。",
|
||||
"fieldUtils.fieldNameDescription.recordField": "记录计数。",
|
||||
"fieldUtils.fieldNameDescription.shapeField": "任意笛卡尔几何形状。",
|
||||
"fieldUtils.fieldNameDescription.stringField": "全文本,如电子邮件正文或产品描述。",
|
||||
"fieldUtils.fieldNameDescription.textField": "全文本,如电子邮件正文或产品描述。",
|
||||
"fieldUtils.fieldNameDescription.unknownField": "未知字段",
|
||||
"fieldUtils.fieldNameDescription.versionField": "软件版本。支持“语义版本控制”优先规则。",
|
||||
"unifiedFieldList.fieldNameSearch.filterByNameLabel": "搜索字段名称",
|
||||
"unifiedFieldList.fieldPopover.addExistsFilterLabel": "筛留存在的字段",
|
||||
"unifiedFieldList.fieldPopover.deleteFieldLabel": "删除数据视图字段",
|
||||
|
|
|
@ -489,7 +489,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
const documentCell = await dataGrid.getCellElement(0, 3);
|
||||
const firstRowContent = await documentCell.getVisibleText();
|
||||
expect(firstRowContent.includes('runtime-message-fieldmock-message_id')).to.be.equal(true);
|
||||
expect(firstRowContent.includes('runtime-message-fieldmock-message')).to.be.equal(true);
|
||||
|
||||
expect(await dataGrid.getDocCount()).to.be(5);
|
||||
});
|
||||
|
@ -503,7 +503,7 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {
|
|||
|
||||
const documentCell = await dataGrid.getCellElement(0, 3);
|
||||
const firstRowContent = await documentCell.getVisibleText();
|
||||
expect(firstRowContent.includes('runtime-message-fieldmock-message_id')).to.be.equal(true);
|
||||
expect(firstRowContent.includes('runtime-message-fieldmock-message')).to.be.equal(true);
|
||||
});
|
||||
|
||||
it('should display results after data view removal on clicking prev generated link', async () => {
|
||||
|
|
|
@ -4512,6 +4512,10 @@
|
|||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/field-utils@link:packages/kbn-field-utils":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
||||
"@kbn/file-upload-plugin@link:x-pack/plugins/file_upload":
|
||||
version "0.0.0"
|
||||
uid ""
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue