mirror of
https://github.com/elastic/kibana.git
synced 2025-04-25 02:09:32 -04:00
[7.x] Index pattern management UI -> TypeScript and New Platform Ready (indexed_fields_table) (#63364) (#63659)
* Index pattern management UI -> TypeScript and New Platform Ready (indexed_fields_table) (#63364) * MIgrated indexed_fields_table to typescript. * Updated docs * Fixed comments * Fixed types * Fixed types. * Fixed types Co-authored-by: Elastic Machine <elasticmachine@users.noreply.github.com>
This commit is contained in:
parent
bc04e709ad
commit
65086bb796
17 changed files with 456 additions and 306 deletions
|
@ -0,0 +1,11 @@
|
||||||
|
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
|
||||||
|
|
||||||
|
[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IndexPatternField](./kibana-plugin-plugins-data-public.indexpatternfield.md) > [indexPattern](./kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md)
|
||||||
|
|
||||||
|
## IndexPatternField.indexPattern property
|
||||||
|
|
||||||
|
<b>Signature:</b>
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
indexPattern?: IndexPattern;
|
||||||
|
```
|
|
@ -27,6 +27,7 @@ export declare class Field implements IFieldType
|
||||||
| [esTypes](./kibana-plugin-plugins-data-public.indexpatternfield.estypes.md) | | <code>string[]</code> | |
|
| [esTypes](./kibana-plugin-plugins-data-public.indexpatternfield.estypes.md) | | <code>string[]</code> | |
|
||||||
| [filterable](./kibana-plugin-plugins-data-public.indexpatternfield.filterable.md) | | <code>boolean</code> | |
|
| [filterable](./kibana-plugin-plugins-data-public.indexpatternfield.filterable.md) | | <code>boolean</code> | |
|
||||||
| [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | <code>any</code> | |
|
| [format](./kibana-plugin-plugins-data-public.indexpatternfield.format.md) | | <code>any</code> | |
|
||||||
|
| [indexPattern](./kibana-plugin-plugins-data-public.indexpatternfield.indexpattern.md) | | <code>IndexPattern</code> | |
|
||||||
| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | <code>string</code> | |
|
| [lang](./kibana-plugin-plugins-data-public.indexpatternfield.lang.md) | | <code>string</code> | |
|
||||||
| [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | <code>string</code> | |
|
| [name](./kibana-plugin-plugins-data-public.indexpatternfield.name.md) | | <code>string</code> | |
|
||||||
| [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) | | <code>Record<string, string></code> | |
|
| [routes](./kibana-plugin-plugins-data-public.indexpatternfield.routes.md) | | <code>Record<string, string></code> | |
|
||||||
|
|
|
@ -16,10 +16,11 @@ exports[`IndexedFieldsTable should filter based on the query bar 1`] = `
|
||||||
"excluded": false,
|
"excluded": false,
|
||||||
"format": undefined,
|
"format": undefined,
|
||||||
"indexPattern": undefined,
|
"indexPattern": undefined,
|
||||||
"info": undefined,
|
"info": Array [],
|
||||||
"name": "Elastic",
|
"name": "Elastic",
|
||||||
"routes": undefined,
|
"routes": undefined,
|
||||||
"searchable": true,
|
"searchable": true,
|
||||||
|
"type": "name",
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -43,7 +44,7 @@ exports[`IndexedFieldsTable should filter based on the type filter 1`] = `
|
||||||
"excluded": false,
|
"excluded": false,
|
||||||
"format": undefined,
|
"format": undefined,
|
||||||
"indexPattern": undefined,
|
"indexPattern": undefined,
|
||||||
"info": undefined,
|
"info": Array [],
|
||||||
"name": "timestamp",
|
"name": "timestamp",
|
||||||
"routes": undefined,
|
"routes": undefined,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
|
@ -70,17 +71,18 @@ exports[`IndexedFieldsTable should render normally 1`] = `
|
||||||
"excluded": false,
|
"excluded": false,
|
||||||
"format": undefined,
|
"format": undefined,
|
||||||
"indexPattern": undefined,
|
"indexPattern": undefined,
|
||||||
"info": undefined,
|
"info": Array [],
|
||||||
"name": "Elastic",
|
"name": "Elastic",
|
||||||
"routes": undefined,
|
"routes": undefined,
|
||||||
"searchable": true,
|
"searchable": true,
|
||||||
|
"type": "name",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"displayName": "timestamp",
|
"displayName": "timestamp",
|
||||||
"excluded": false,
|
"excluded": false,
|
||||||
"format": undefined,
|
"format": undefined,
|
||||||
"indexPattern": undefined,
|
"indexPattern": undefined,
|
||||||
"info": undefined,
|
"info": Array [],
|
||||||
"name": "timestamp",
|
"name": "timestamp",
|
||||||
"routes": undefined,
|
"routes": undefined,
|
||||||
"type": "date",
|
"type": "date",
|
||||||
|
@ -90,7 +92,7 @@ exports[`IndexedFieldsTable should render normally 1`] = `
|
||||||
"excluded": false,
|
"excluded": false,
|
||||||
"format": undefined,
|
"format": undefined,
|
||||||
"indexPattern": undefined,
|
"indexPattern": undefined,
|
||||||
"info": undefined,
|
"info": Array [],
|
||||||
"name": "conflictingField",
|
"name": "conflictingField",
|
||||||
"routes": undefined,
|
"routes": undefined,
|
||||||
"type": "conflict",
|
"type": "conflict",
|
|
@ -98,19 +98,26 @@ exports[`Table should render normally 1`] = `
|
||||||
Array [
|
Array [
|
||||||
Object {
|
Object {
|
||||||
"displayName": "Elastic",
|
"displayName": "Elastic",
|
||||||
"info": Object {},
|
"excluded": false,
|
||||||
|
"format": "",
|
||||||
|
"info": Array [],
|
||||||
"name": "Elastic",
|
"name": "Elastic",
|
||||||
"searchable": true,
|
"searchable": true,
|
||||||
|
"type": "name",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"displayName": "timestamp",
|
"displayName": "timestamp",
|
||||||
"info": Object {},
|
"excluded": false,
|
||||||
|
"format": "YYYY-MM-DD",
|
||||||
|
"info": Array [],
|
||||||
"name": "timestamp",
|
"name": "timestamp",
|
||||||
"type": "date",
|
"type": "date",
|
||||||
},
|
},
|
||||||
Object {
|
Object {
|
||||||
"displayName": "conflictingField",
|
"displayName": "conflictingField",
|
||||||
"info": Object {},
|
"excluded": false,
|
||||||
|
"format": "",
|
||||||
|
"info": Array [],
|
||||||
"name": "conflictingField",
|
"name": "conflictingField",
|
||||||
"type": "conflict",
|
"type": "conflict",
|
||||||
},
|
},
|
|
@ -1,231 +0,0 @@
|
||||||
/*
|
|
||||||
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
||||||
* license agreements. See the NOTICE file distributed with
|
|
||||||
* this work for additional information regarding copyright
|
|
||||||
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
||||||
* the Apache License, Version 2.0 (the "License"); you may
|
|
||||||
* not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing,
|
|
||||||
* software distributed under the License is distributed on an
|
|
||||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
||||||
* KIND, either express or implied. See the License for the
|
|
||||||
* specific language governing permissions and limitations
|
|
||||||
* under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
import React, { PureComponent } from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
|
|
||||||
import { EuiIcon, EuiInMemoryTable, EuiIconTip } from '@elastic/eui';
|
|
||||||
|
|
||||||
import { i18n } from '@kbn/i18n';
|
|
||||||
|
|
||||||
export class Table extends PureComponent {
|
|
||||||
static propTypes = {
|
|
||||||
indexPattern: PropTypes.object.isRequired,
|
|
||||||
items: PropTypes.array.isRequired,
|
|
||||||
editField: PropTypes.func.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
renderBooleanTemplate(value, label) {
|
|
||||||
return value ? <EuiIcon type="dot" color="secondary" aria-label={label} /> : <span />;
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFieldName(name, field) {
|
|
||||||
const { indexPattern } = this.props;
|
|
||||||
|
|
||||||
const infoLabel = i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.additionalInfoAriaLabel',
|
|
||||||
{ defaultMessage: 'Additional field information' }
|
|
||||||
);
|
|
||||||
const timeLabel = i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.primaryTimeAriaLabel',
|
|
||||||
{ defaultMessage: 'Primary time field' }
|
|
||||||
);
|
|
||||||
const timeContent = i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.primaryTimeTooltip',
|
|
||||||
{ defaultMessage: 'This field represents the time that events occurred.' }
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
{name}
|
|
||||||
{field.info && field.info.length ? (
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<EuiIconTip
|
|
||||||
type="questionInCircle"
|
|
||||||
color="primary"
|
|
||||||
aria-label={infoLabel}
|
|
||||||
content={field.info.map((info, i) => (
|
|
||||||
<div key={i}>{info}</div>
|
|
||||||
))}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
{indexPattern.timeFieldName === name ? (
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<EuiIconTip type="clock" color="primary" aria-label={timeLabel} content={timeContent} />
|
|
||||||
</span>
|
|
||||||
) : null}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
renderFieldType(type, isConflict) {
|
|
||||||
const label = i18n.translate('kbn.management.editIndexPattern.fields.table.multiTypeAria', {
|
|
||||||
defaultMessage: 'Multiple type field',
|
|
||||||
});
|
|
||||||
const content = i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.multiTypeTooltip',
|
|
||||||
{
|
|
||||||
defaultMessage:
|
|
||||||
'The type of this field changes across indices. It is unavailable for many analysis functions.',
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
{type}
|
|
||||||
{isConflict ? (
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<EuiIconTip type="alert" color="warning" aria-label={label} content={content} />
|
|
||||||
</span>
|
|
||||||
) : (
|
|
||||||
''
|
|
||||||
)}
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { items, editField } = this.props;
|
|
||||||
|
|
||||||
const pagination = {
|
|
||||||
initialPageSize: 10,
|
|
||||||
pageSizeOptions: [5, 10, 25, 50],
|
|
||||||
};
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
field: 'displayName',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.nameHeader', {
|
|
||||||
defaultMessage: 'Name',
|
|
||||||
}),
|
|
||||||
dataType: 'string',
|
|
||||||
sortable: true,
|
|
||||||
render: (value, field) => {
|
|
||||||
return this.renderFieldName(value, field);
|
|
||||||
},
|
|
||||||
width: '38%',
|
|
||||||
'data-test-subj': 'indexedFieldName',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'type',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.typeHeader', {
|
|
||||||
defaultMessage: 'Type',
|
|
||||||
}),
|
|
||||||
dataType: 'string',
|
|
||||||
sortable: true,
|
|
||||||
render: value => {
|
|
||||||
return this.renderFieldType(value, value === 'conflict');
|
|
||||||
},
|
|
||||||
'data-test-subj': 'indexedFieldType',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'format',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.formatHeader', {
|
|
||||||
defaultMessage: 'Format',
|
|
||||||
}),
|
|
||||||
dataType: 'string',
|
|
||||||
sortable: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'searchable',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.searchableHeader', {
|
|
||||||
defaultMessage: 'Searchable',
|
|
||||||
}),
|
|
||||||
description: i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.searchableDescription',
|
|
||||||
{ defaultMessage: 'These fields can be used in the filter bar' }
|
|
||||||
),
|
|
||||||
dataType: 'boolean',
|
|
||||||
sortable: true,
|
|
||||||
render: value =>
|
|
||||||
this.renderBooleanTemplate(
|
|
||||||
value,
|
|
||||||
i18n.translate('kbn.management.editIndexPattern.fields.table.isSearchableAria', {
|
|
||||||
defaultMessage: 'Is searchable',
|
|
||||||
})
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'aggregatable',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.aggregatableLabel', {
|
|
||||||
defaultMessage: 'Aggregatable',
|
|
||||||
}),
|
|
||||||
description: i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.aggregatableDescription',
|
|
||||||
{ defaultMessage: 'These fields can be used in visualization aggregations' }
|
|
||||||
),
|
|
||||||
dataType: 'boolean',
|
|
||||||
sortable: true,
|
|
||||||
render: value =>
|
|
||||||
this.renderBooleanTemplate(
|
|
||||||
value,
|
|
||||||
i18n.translate('kbn.management.editIndexPattern.fields.table.isAggregatableAria', {
|
|
||||||
defaultMessage: 'Is aggregatable',
|
|
||||||
})
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
field: 'excluded',
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.excludedLabel', {
|
|
||||||
defaultMessage: 'Excluded',
|
|
||||||
}),
|
|
||||||
description: i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.excludedDescription',
|
|
||||||
{ defaultMessage: 'Fields that are excluded from _source when it is fetched' }
|
|
||||||
),
|
|
||||||
dataType: 'boolean',
|
|
||||||
sortable: true,
|
|
||||||
render: value =>
|
|
||||||
this.renderBooleanTemplate(
|
|
||||||
value,
|
|
||||||
i18n.translate('kbn.management.editIndexPattern.fields.table.isExcludedAria', {
|
|
||||||
defaultMessage: 'Is excluded',
|
|
||||||
})
|
|
||||||
),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: '',
|
|
||||||
actions: [
|
|
||||||
{
|
|
||||||
name: i18n.translate('kbn.management.editIndexPattern.fields.table.editLabel', {
|
|
||||||
defaultMessage: 'Edit',
|
|
||||||
}),
|
|
||||||
description: i18n.translate(
|
|
||||||
'kbn.management.editIndexPattern.fields.table.editDescription',
|
|
||||||
{ defaultMessage: 'Edit' }
|
|
||||||
),
|
|
||||||
icon: 'pencil',
|
|
||||||
onClick: editField,
|
|
||||||
type: 'icon',
|
|
||||||
'data-test-subj': 'editFieldFormat',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
width: '40px',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
|
||||||
<EuiInMemoryTable items={items} columns={columns} pagination={pagination} sorting={true} />
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -19,31 +19,53 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
import { shallowWithI18nProvider } from 'test_utils/enzyme_helpers';
|
import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public';
|
||||||
|
import { IndexedFieldItem } from '../../types';
|
||||||
import { Table } from '../table';
|
import { Table } from './table';
|
||||||
|
|
||||||
const indexPattern = {
|
const indexPattern = {
|
||||||
timeFieldName: 'timestamp',
|
timeFieldName: 'timestamp',
|
||||||
};
|
} as IIndexPattern;
|
||||||
|
|
||||||
const items = [
|
const items: IndexedFieldItem[] = [
|
||||||
{ name: 'Elastic', displayName: 'Elastic', searchable: true, info: {} },
|
{
|
||||||
{ name: 'timestamp', displayName: 'timestamp', type: 'date', info: {} },
|
name: 'Elastic',
|
||||||
{ name: 'conflictingField', displayName: 'conflictingField', type: 'conflict', info: {} },
|
displayName: 'Elastic',
|
||||||
|
searchable: true,
|
||||||
|
info: [],
|
||||||
|
type: 'name',
|
||||||
|
excluded: false,
|
||||||
|
format: '',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'timestamp',
|
||||||
|
displayName: 'timestamp',
|
||||||
|
type: 'date',
|
||||||
|
info: [],
|
||||||
|
excluded: false,
|
||||||
|
format: 'YYYY-MM-DD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'conflictingField',
|
||||||
|
displayName: 'conflictingField',
|
||||||
|
type: 'conflict',
|
||||||
|
info: [],
|
||||||
|
excluded: false,
|
||||||
|
format: '',
|
||||||
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
describe('Table', () => {
|
describe('Table', () => {
|
||||||
it('should render normally', async () => {
|
test('should render normally', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render normal field name', async () => {
|
test('should render normal field name', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -51,8 +73,8 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render timestamp field name', async () => {
|
test('should render timestamp field name', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -60,8 +82,8 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render the boolean template (true)', async () => {
|
test('should render the boolean template (true)', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -69,8 +91,8 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render the boolean template (false)', async () => {
|
test('should render the boolean template (false)', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -78,8 +100,8 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render normal type', async () => {
|
test('should render normal type', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -87,8 +109,8 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render conflicting type', async () => {
|
test('should render conflicting type', () => {
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
<Table indexPattern={indexPattern} items={items} editField={() => {}} />
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -96,10 +118,10 @@ describe('Table', () => {
|
||||||
expect(tableCell).toMatchSnapshot();
|
expect(tableCell).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should allow edits', () => {
|
test('should allow edits', () => {
|
||||||
const editField = jest.fn();
|
const editField = jest.fn();
|
||||||
|
|
||||||
const component = shallowWithI18nProvider(
|
const component = shallow(
|
||||||
<Table indexPattern={indexPattern} items={items} editField={editField} />
|
<Table indexPattern={indexPattern} items={items} editField={editField} />
|
||||||
);
|
);
|
||||||
|
|
|
@ -0,0 +1,281 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import React, { PureComponent } from 'react';
|
||||||
|
|
||||||
|
import { EuiIcon, EuiInMemoryTable, EuiIconTip, EuiBasicTableColumn } from '@elastic/eui';
|
||||||
|
|
||||||
|
import { i18n } from '@kbn/i18n';
|
||||||
|
|
||||||
|
import { IIndexPattern } from '../../../../../../../../../../../plugins/data/public';
|
||||||
|
import { IndexedFieldItem } from '../../types';
|
||||||
|
|
||||||
|
// localized labels
|
||||||
|
const additionalInfoAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.additionalInfoAriaLabel',
|
||||||
|
{ defaultMessage: 'Additional field information' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const primaryTimeAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.primaryTimeAriaLabel',
|
||||||
|
{ defaultMessage: 'Primary time field' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const primaryTimeTooltip = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.primaryTimeTooltip',
|
||||||
|
{ defaultMessage: 'This field represents the time that events occurred.' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const multiTypeAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.multiTypeAria',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Multiple type field',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const multiTypeTooltip = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.multiTypeTooltip',
|
||||||
|
{
|
||||||
|
defaultMessage:
|
||||||
|
'The type of this field changes across indices. It is unavailable for many analysis functions.',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const nameHeader = i18n.translate('kbn.management.editIndexPattern.fields.table.nameHeader', {
|
||||||
|
defaultMessage: 'Name',
|
||||||
|
});
|
||||||
|
|
||||||
|
const typeHeader = i18n.translate('kbn.management.editIndexPattern.fields.table.typeHeader', {
|
||||||
|
defaultMessage: 'Type',
|
||||||
|
});
|
||||||
|
|
||||||
|
const formatHeader = i18n.translate('kbn.management.editIndexPattern.fields.table.formatHeader', {
|
||||||
|
defaultMessage: 'Format',
|
||||||
|
});
|
||||||
|
|
||||||
|
const searchableHeader = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.searchableHeader',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Searchable',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const searchableDescription = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.searchableDescription',
|
||||||
|
{ defaultMessage: 'These fields can be used in the filter bar' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const isSearchableAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.isSearchableAria',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Is searchable',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const aggregatableLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.aggregatableLabel',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Aggregatable',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const aggregatableDescription = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.aggregatableDescription',
|
||||||
|
{ defaultMessage: 'These fields can be used in visualization aggregations' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const isAggregatableAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.isAggregatableAria',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Is aggregatable',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const excludedLabel = i18n.translate('kbn.management.editIndexPattern.fields.table.excludedLabel', {
|
||||||
|
defaultMessage: 'Excluded',
|
||||||
|
});
|
||||||
|
|
||||||
|
const excludedDescription = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.excludedDescription',
|
||||||
|
{ defaultMessage: 'Fields that are excluded from _source when it is fetched' }
|
||||||
|
);
|
||||||
|
|
||||||
|
const isExcludedAriaLabel = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.isExcludedAria',
|
||||||
|
{
|
||||||
|
defaultMessage: 'Is excluded',
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
const editLabel = i18n.translate('kbn.management.editIndexPattern.fields.table.editLabel', {
|
||||||
|
defaultMessage: 'Edit',
|
||||||
|
});
|
||||||
|
|
||||||
|
const editDescription = i18n.translate(
|
||||||
|
'kbn.management.editIndexPattern.fields.table.editDescription',
|
||||||
|
{ defaultMessage: 'Edit' }
|
||||||
|
);
|
||||||
|
|
||||||
|
interface IndexedFieldProps {
|
||||||
|
indexPattern: IIndexPattern;
|
||||||
|
items: IndexedFieldItem[];
|
||||||
|
editField: (field: IndexedFieldItem) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Table extends PureComponent<IndexedFieldProps> {
|
||||||
|
renderBooleanTemplate(value: string, arialLabel: string) {
|
||||||
|
return value ? <EuiIcon type="dot" color="secondary" aria-label={arialLabel} /> : <span />;
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFieldName(name: string, field: IndexedFieldItem) {
|
||||||
|
const { indexPattern } = this.props;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{name}
|
||||||
|
{field.info && field.info.length ? (
|
||||||
|
<span>
|
||||||
|
|
||||||
|
<EuiIconTip
|
||||||
|
type="questionInCircle"
|
||||||
|
color="primary"
|
||||||
|
aria-label={additionalInfoAriaLabel}
|
||||||
|
content={field.info.map((info: string, i: number) => (
|
||||||
|
<div key={i}>{info}</div>
|
||||||
|
))}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
{indexPattern.timeFieldName === name ? (
|
||||||
|
<span>
|
||||||
|
|
||||||
|
<EuiIconTip
|
||||||
|
type="clock"
|
||||||
|
color="primary"
|
||||||
|
aria-label={primaryTimeAriaLabel}
|
||||||
|
content={primaryTimeTooltip}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : null}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
renderFieldType(type: string, isConflict: boolean) {
|
||||||
|
return (
|
||||||
|
<span>
|
||||||
|
{type}
|
||||||
|
{isConflict ? (
|
||||||
|
<span>
|
||||||
|
|
||||||
|
<EuiIconTip
|
||||||
|
type="alert"
|
||||||
|
color="warning"
|
||||||
|
aria-label={multiTypeAriaLabel}
|
||||||
|
content={multiTypeTooltip}
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
) : (
|
||||||
|
''
|
||||||
|
)}
|
||||||
|
</span>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const { items, editField } = this.props;
|
||||||
|
|
||||||
|
const pagination = {
|
||||||
|
initialPageSize: 10,
|
||||||
|
pageSizeOptions: [5, 10, 25, 50],
|
||||||
|
};
|
||||||
|
|
||||||
|
const columns: Array<EuiBasicTableColumn<IndexedFieldItem>> = [
|
||||||
|
{
|
||||||
|
field: 'displayName',
|
||||||
|
name: nameHeader,
|
||||||
|
dataType: 'string',
|
||||||
|
sortable: true,
|
||||||
|
render: (value: string, field: IndexedFieldItem) => {
|
||||||
|
return this.renderFieldName(value, field);
|
||||||
|
},
|
||||||
|
width: '38%',
|
||||||
|
'data-test-subj': 'indexedFieldName',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'type',
|
||||||
|
name: typeHeader,
|
||||||
|
dataType: 'string',
|
||||||
|
sortable: true,
|
||||||
|
render: (value: string) => {
|
||||||
|
return this.renderFieldType(value, value === 'conflict');
|
||||||
|
},
|
||||||
|
'data-test-subj': 'indexedFieldType',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'format',
|
||||||
|
name: formatHeader,
|
||||||
|
dataType: 'string',
|
||||||
|
sortable: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'searchable',
|
||||||
|
name: searchableHeader,
|
||||||
|
description: searchableDescription,
|
||||||
|
dataType: 'boolean',
|
||||||
|
sortable: true,
|
||||||
|
render: (value: string) => this.renderBooleanTemplate(value, isSearchableAriaLabel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'aggregatable',
|
||||||
|
name: aggregatableLabel,
|
||||||
|
description: aggregatableDescription,
|
||||||
|
dataType: 'boolean',
|
||||||
|
sortable: true,
|
||||||
|
render: (value: string) => this.renderBooleanTemplate(value, isAggregatableAriaLabel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
field: 'excluded',
|
||||||
|
name: excludedLabel,
|
||||||
|
description: excludedDescription,
|
||||||
|
dataType: 'boolean',
|
||||||
|
sortable: true,
|
||||||
|
render: (value: string) => this.renderBooleanTemplate(value, isExcludedAriaLabel),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '',
|
||||||
|
actions: [
|
||||||
|
{
|
||||||
|
name: editLabel,
|
||||||
|
description: editDescription,
|
||||||
|
icon: 'pencil',
|
||||||
|
onClick: editField,
|
||||||
|
type: 'icon',
|
||||||
|
'data-test-subj': 'editFieldFormat',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
width: '40px',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EuiInMemoryTable items={items} columns={columns} pagination={pagination} sorting={true} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,8 @@
|
||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import { shallow } from 'enzyme';
|
import { shallow } from 'enzyme';
|
||||||
|
import { IndexPatternField, IIndexPattern } from '../../../../../../../../../plugins/data/public';
|
||||||
import { IndexedFieldsTable } from '../indexed_fields_table';
|
import { IndexedFieldsTable } from './indexed_fields_table';
|
||||||
|
|
||||||
jest.mock('@elastic/eui', () => ({
|
jest.mock('@elastic/eui', () => ({
|
||||||
EuiFlexGroup: 'eui-flex-group',
|
EuiFlexGroup: 'eui-flex-group',
|
||||||
|
@ -29,7 +29,7 @@ jest.mock('@elastic/eui', () => ({
|
||||||
EuiInMemoryTable: 'eui-in-memory-table',
|
EuiInMemoryTable: 'eui-in-memory-table',
|
||||||
}));
|
}));
|
||||||
|
|
||||||
jest.mock('../components/table', () => ({
|
jest.mock('./components/table', () => ({
|
||||||
// Note: this seems to fix React complaining about non lowercase attributes
|
// Note: this seems to fix React complaining about non lowercase attributes
|
||||||
Table: () => {
|
Table: () => {
|
||||||
return 'table';
|
return 'table';
|
||||||
|
@ -37,27 +37,37 @@ jest.mock('../components/table', () => ({
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const helpers = {
|
const helpers = {
|
||||||
redirectToRoute: () => {},
|
redirectToRoute: (obj: any, route: string) => {},
|
||||||
|
getFieldInfo: () => [],
|
||||||
};
|
};
|
||||||
|
|
||||||
const fields = [
|
const fields = [
|
||||||
{ name: 'Elastic', displayName: 'Elastic', searchable: true },
|
{
|
||||||
|
name: 'Elastic',
|
||||||
|
displayName: 'Elastic',
|
||||||
|
searchable: true,
|
||||||
|
type: 'name',
|
||||||
|
},
|
||||||
{ name: 'timestamp', displayName: 'timestamp', type: 'date' },
|
{ name: 'timestamp', displayName: 'timestamp', type: 'date' },
|
||||||
{ name: 'conflictingField', displayName: 'conflictingField', type: 'conflict' },
|
{ name: 'conflictingField', displayName: 'conflictingField', type: 'conflict' },
|
||||||
];
|
] as IndexPatternField[];
|
||||||
|
|
||||||
const indexPattern = {
|
const indexPattern = ({
|
||||||
getNonScriptedFields: () => fields,
|
getNonScriptedFields: () => fields,
|
||||||
};
|
} as unknown) as IIndexPattern;
|
||||||
|
|
||||||
describe('IndexedFieldsTable', () => {
|
describe('IndexedFieldsTable', () => {
|
||||||
it('should render normally', async () => {
|
test('should render normally', async () => {
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<IndexedFieldsTable
|
<IndexedFieldsTable
|
||||||
fields={fields}
|
fields={fields}
|
||||||
indexPattern={indexPattern}
|
indexPattern={indexPattern}
|
||||||
helpers={helpers}
|
helpers={helpers}
|
||||||
fieldWildcardMatcher={() => {}}
|
fieldWildcardMatcher={() => {
|
||||||
|
return () => false;
|
||||||
|
}}
|
||||||
|
indexedFieldTypeFilter=""
|
||||||
|
fieldFilter=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -67,13 +77,17 @@ describe('IndexedFieldsTable', () => {
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter based on the query bar', async () => {
|
test('should filter based on the query bar', async () => {
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<IndexedFieldsTable
|
<IndexedFieldsTable
|
||||||
fields={fields}
|
fields={fields}
|
||||||
indexPattern={indexPattern}
|
indexPattern={indexPattern}
|
||||||
helpers={helpers}
|
helpers={helpers}
|
||||||
fieldWildcardMatcher={() => {}}
|
fieldWildcardMatcher={() => {
|
||||||
|
return () => false;
|
||||||
|
}}
|
||||||
|
indexedFieldTypeFilter=""
|
||||||
|
fieldFilter=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -84,13 +98,17 @@ describe('IndexedFieldsTable', () => {
|
||||||
expect(component).toMatchSnapshot();
|
expect(component).toMatchSnapshot();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should filter based on the type filter', async () => {
|
test('should filter based on the type filter', async () => {
|
||||||
const component = shallow(
|
const component = shallow(
|
||||||
<IndexedFieldsTable
|
<IndexedFieldsTable
|
||||||
fields={fields}
|
fields={fields}
|
||||||
indexPattern={indexPattern}
|
indexPattern={indexPattern}
|
||||||
helpers={helpers}
|
helpers={helpers}
|
||||||
fieldWildcardMatcher={() => {}}
|
fieldWildcardMatcher={() => {
|
||||||
|
return () => false;
|
||||||
|
}}
|
||||||
|
indexedFieldTypeFilter=""
|
||||||
|
fieldFilter=""
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
|
|
|
@ -18,26 +18,33 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { createSelector } from 'reselect';
|
import { createSelector } from 'reselect';
|
||||||
|
import { IndexPatternField, IIndexPattern } from '../../../../../../../../../plugins/data/public';
|
||||||
import { Table } from './components/table';
|
import { Table } from './components/table';
|
||||||
import { getFieldFormat } from './lib';
|
import { getFieldFormat } from './lib';
|
||||||
|
import { IndexedFieldItem } from './types';
|
||||||
|
|
||||||
export class IndexedFieldsTable extends Component {
|
interface IndexedFieldsTableProps {
|
||||||
static propTypes = {
|
fields: IndexPatternField[];
|
||||||
fields: PropTypes.array.isRequired,
|
indexPattern: IIndexPattern;
|
||||||
indexPattern: PropTypes.object.isRequired,
|
fieldFilter?: string;
|
||||||
fieldFilter: PropTypes.string,
|
indexedFieldTypeFilter?: string;
|
||||||
indexedFieldTypeFilter: PropTypes.string,
|
helpers: {
|
||||||
helpers: PropTypes.shape({
|
redirectToRoute: (obj: any, route: string) => void;
|
||||||
redirectToRoute: PropTypes.func.isRequired,
|
getFieldInfo: (indexPattern: IIndexPattern, field: string) => string[];
|
||||||
getFieldInfo: PropTypes.func,
|
|
||||||
}),
|
|
||||||
fieldWildcardMatcher: PropTypes.func.isRequired,
|
|
||||||
};
|
};
|
||||||
|
fieldWildcardMatcher: (filters: any[]) => (val: any) => boolean;
|
||||||
|
}
|
||||||
|
|
||||||
constructor(props) {
|
interface IndexedFieldsTableState {
|
||||||
|
fields: IndexedFieldItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export class IndexedFieldsTable extends Component<
|
||||||
|
IndexedFieldsTableProps,
|
||||||
|
IndexedFieldsTableState
|
||||||
|
> {
|
||||||
|
constructor(props: IndexedFieldsTableProps) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
|
@ -45,7 +52,7 @@ export class IndexedFieldsTable extends Component {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
UNSAFE_componentWillReceiveProps(nextProps) {
|
UNSAFE_componentWillReceiveProps(nextProps: IndexedFieldsTableProps) {
|
||||||
if (nextProps.fields !== this.props.fields) {
|
if (nextProps.fields !== this.props.fields) {
|
||||||
this.setState({
|
this.setState({
|
||||||
fields: this.mapFields(nextProps.fields),
|
fields: this.mapFields(nextProps.fields),
|
||||||
|
@ -53,10 +60,11 @@ export class IndexedFieldsTable extends Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapFields(fields) {
|
mapFields(fields: IndexPatternField[]): IndexedFieldItem[] {
|
||||||
const { indexPattern, fieldWildcardMatcher, helpers } = this.props;
|
const { indexPattern, fieldWildcardMatcher, helpers } = this.props;
|
||||||
const sourceFilters =
|
const sourceFilters =
|
||||||
indexPattern.sourceFilters && indexPattern.sourceFilters.map(f => f.value);
|
indexPattern.sourceFilters &&
|
||||||
|
indexPattern.sourceFilters.map((f: Record<string, any>) => f.value);
|
||||||
const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []);
|
const fieldWildcardMatch = fieldWildcardMatcher(sourceFilters || []);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -77,9 +85,10 @@ export class IndexedFieldsTable extends Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
getFilteredFields = createSelector(
|
getFilteredFields = createSelector(
|
||||||
state => state.fields,
|
(state: IndexedFieldsTableState) => state.fields,
|
||||||
(state, props) => props.fieldFilter,
|
(state: IndexedFieldsTableState, props: IndexedFieldsTableProps) => props.fieldFilter,
|
||||||
(state, props) => props.indexedFieldTypeFilter,
|
(state: IndexedFieldsTableState, props: IndexedFieldsTableProps) =>
|
||||||
|
props.indexedFieldTypeFilter,
|
||||||
(fields, fieldFilter, indexedFieldTypeFilter) => {
|
(fields, fieldFilter, indexedFieldTypeFilter) => {
|
||||||
if (fieldFilter) {
|
if (fieldFilter) {
|
||||||
const normalizedFieldFilter = fieldFilter.toLowerCase();
|
const normalizedFieldFilter = fieldFilter.toLowerCase();
|
|
@ -17,9 +17,10 @@
|
||||||
* under the License.
|
* under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getFieldFormat } from '../get_field_format';
|
import { IIndexPattern } from '../../../../../../../../../../plugins/data/public';
|
||||||
|
import { getFieldFormat } from './get_field_format';
|
||||||
|
|
||||||
const indexPattern = {
|
const indexPattern = ({
|
||||||
fieldFormatMap: {
|
fieldFormatMap: {
|
||||||
Elastic: {
|
Elastic: {
|
||||||
type: {
|
type: {
|
||||||
|
@ -27,26 +28,26 @@ const indexPattern = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
} as unknown) as IIndexPattern;
|
||||||
|
|
||||||
describe('getFieldFormat', () => {
|
describe('getFieldFormat', () => {
|
||||||
it('should handle no arguments', () => {
|
test('should handle no arguments', () => {
|
||||||
expect(getFieldFormat()).toEqual('');
|
expect(getFieldFormat()).toEqual('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle no field name', () => {
|
test('should handle no field name', () => {
|
||||||
expect(getFieldFormat(indexPattern)).toEqual('');
|
expect(getFieldFormat(indexPattern)).toEqual('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle empty name', () => {
|
test('should handle empty name', () => {
|
||||||
expect(getFieldFormat(indexPattern, '')).toEqual('');
|
expect(getFieldFormat(indexPattern, '')).toEqual('');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle undefined field name', () => {
|
test('should handle undefined field name', () => {
|
||||||
expect(getFieldFormat(indexPattern, 'none')).toEqual(undefined);
|
expect(getFieldFormat(indexPattern, 'none')).toEqual(undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should retrieve field format', () => {
|
test('should retrieve field format', () => {
|
||||||
expect(getFieldFormat(indexPattern, 'Elastic')).toEqual('string');
|
expect(getFieldFormat(indexPattern, 'Elastic')).toEqual('string');
|
||||||
});
|
});
|
||||||
});
|
});
|
|
@ -18,8 +18,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
|
import { IIndexPattern } from '../../../../../../../../../../plugins/data/public';
|
||||||
|
|
||||||
export function getFieldFormat(indexPattern, fieldName) {
|
export function getFieldFormat(indexPattern?: IIndexPattern, fieldName?: string): string {
|
||||||
return indexPattern && fieldName
|
return indexPattern && fieldName
|
||||||
? get(indexPattern, ['fieldFormatMap', fieldName, 'type', 'title'])
|
? get(indexPattern, ['fieldFormatMap', fieldName, 'type', 'title'])
|
||||||
: '';
|
: '';
|
|
@ -0,0 +1,25 @@
|
||||||
|
/*
|
||||||
|
* Licensed to Elasticsearch B.V. under one or more contributor
|
||||||
|
* license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright
|
||||||
|
* ownership. Elasticsearch B.V. licenses this file to you under
|
||||||
|
* the Apache License, Version 2.0 (the "License"); you may
|
||||||
|
* not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { IFieldType } from '../../../../../../../../../plugins/data/public';
|
||||||
|
|
||||||
|
export interface IndexedFieldItem extends IFieldType {
|
||||||
|
info: string[];
|
||||||
|
excluded: boolean;
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ export class Field implements IFieldType {
|
||||||
scripted?: boolean;
|
scripted?: boolean;
|
||||||
subType?: IFieldSubType;
|
subType?: IFieldSubType;
|
||||||
displayName?: string;
|
displayName?: string;
|
||||||
|
indexPattern?: IndexPattern;
|
||||||
format: any;
|
format: any;
|
||||||
routes: Record<string, string> = {
|
routes: Record<string, string> = {
|
||||||
edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}',
|
edit: '/management/kibana/index_patterns/{{indexPattern.id}}/field/{{name}}',
|
||||||
|
|
|
@ -953,6 +953,8 @@ export class IndexPatternField implements IFieldType {
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
format: any;
|
format: any;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
|
indexPattern?: IndexPattern;
|
||||||
|
// (undocumented)
|
||||||
lang?: string;
|
lang?: string;
|
||||||
// (undocumented)
|
// (undocumented)
|
||||||
name: string;
|
name: string;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue