Rollup index pattern list fixes (#105458) (#105587)

* fix index pattern field list and improve typescript

Co-authored-by: Matthew Kime <matt@mattki.me>
This commit is contained in:
Kibana Machine 2021-07-14 10:18:19 -04:00 committed by GitHub
parent d019db6fef
commit dedbcdb391
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 307 additions and 53 deletions

View file

@ -0,0 +1,19 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IndexPatternType](./kibana-plugin-plugins-data-public.indexpatterntype.md)
## IndexPatternType enum
<b>Signature:</b>
```typescript
export declare enum IndexPatternType
```
## Enumeration Members
| Member | Value | Description |
| --- | --- | --- |
| DEFAULT | <code>&quot;default&quot;</code> | |
| ROLLUP | <code>&quot;rollup&quot;</code> | |

View file

@ -15,4 +15,5 @@ export interface TypeMeta
| Property | Type | Description |
| --- | --- | --- |
| [aggs](./kibana-plugin-plugins-data-public.indexpatterntypemeta.aggs.md) | <code>Record&lt;string, AggregationRestrictions&gt;</code> | |
| [params](./kibana-plugin-plugins-data-public.indexpatterntypemeta.params.md) | <code>{</code><br/><code> rollup_index: string;</code><br/><code> }</code> | |

View file

@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [IndexPatternTypeMeta](./kibana-plugin-plugins-data-public.indexpatterntypemeta.md) &gt; [params](./kibana-plugin-plugins-data-public.indexpatterntypemeta.params.md)
## IndexPatternTypeMeta.params property
<b>Signature:</b>
```typescript
params?: {
rollup_index: string;
};
```

View file

@ -31,6 +31,7 @@
| --- | --- |
| [BUCKET\_TYPES](./kibana-plugin-plugins-data-public.bucket_types.md) | |
| [ES\_FIELD\_TYPES](./kibana-plugin-plugins-data-public.es_field_types.md) | \* |
| [IndexPatternType](./kibana-plugin-plugins-data-public.indexpatterntype.md) | |
| [KBN\_FIELD\_TYPES](./kibana-plugin-plugins-data-public.kbn_field_types.md) | \* |
| [METRIC\_TYPES](./kibana-plugin-plugins-data-public.metric_types.md) | |
| [QuerySuggestionTypes](./kibana-plugin-plugins-data-public.querysuggestiontypes.md) | |

View file

@ -161,9 +161,17 @@ export type AggregationRestrictions = Record<
time_zone?: string;
}
>;
export interface TypeMeta {
aggs?: Record<string, AggregationRestrictions>;
[key: string]: any;
params?: {
rollup_index: string;
};
}
export enum IndexPatternType {
DEFAULT = 'default',
ROLLUP = 'rollup',
}
export type FieldSpecConflictDescriptions = Record<string, string[]>;

View file

@ -269,6 +269,7 @@ export {
IndexPatternLoadExpressionFunctionDefinition,
fieldList,
INDEX_PATTERN_SAVED_OBJECT_TYPE,
IndexPatternType,
} from '../common';
export { DuplicateIndexPatternError } from '../common/index_patterns/errors';

View file

@ -1694,14 +1694,26 @@ export class IndexPatternsService {
updateSavedObject(indexPattern: IndexPattern, saveAttempts?: number, ignoreErrors?: boolean): Promise<void | Error>;
}
// Warning: (ae-missing-release-tag) "IndexPatternType" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export enum IndexPatternType {
// (undocumented)
DEFAULT = "default",
// (undocumented)
ROLLUP = "rollup"
}
// Warning: (ae-missing-release-tag) "TypeMeta" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
//
// @public (undocumented)
export interface IndexPatternTypeMeta {
// (undocumented)
[key: string]: any;
// (undocumented)
aggs?: Record<string, IndexPatternAggRestrictions>;
// (undocumented)
params?: {
rollup_index: string;
};
}
// Warning: (ae-missing-release-tag) "injectReferences" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
@ -2772,20 +2784,20 @@ export interface WaitUntilNextSessionCompletesOptions {
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:428:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:429:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:432:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:433:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:436:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "IpAddress" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:425:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:429:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:433:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:434:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:437:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/search/session/session_service.ts:62:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts

View file

@ -1,5 +1,148 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`IndexedFieldsTable IndexedFieldsTable with rollup index pattern should render normally 1`] = `
<div>
<Table
deleteField={[Function]}
editField={[Function]}
indexPattern={
Object {
"getFormatterForFieldNoDefault": [Function],
"getNonScriptedFields": [Function],
"type": "rollup",
"typeMeta": Object {
"aggs": Object {
"avg": Object {
"amount": Object {
"agg": "avg",
},
},
"date_histogram": Object {
"timestamp": Object {
"agg": "date_histogram",
"delay": "30s",
"fixed_interval": "30s",
"time_zone": "UTC",
},
},
"histogram": Object {
"amount": Object {
"agg": "histogram",
"interval": 5,
},
},
"max": Object {
"amount": Object {
"agg": "max",
},
},
"min": Object {
"amount": Object {
"agg": "min",
},
},
"sum": Object {
"amount": Object {
"agg": "sum",
},
},
"terms": Object {
"Elastic": Object {
"agg": "terms",
},
},
"value_count": Object {
"amount": Object {
"agg": "value_count",
},
},
},
"params": Object {
"rollup-index": "rollup",
},
},
}
}
items={
Array [
Object {
"displayName": "Elastic",
"esTypes": Array [
"keyword",
],
"excluded": false,
"format": "",
"hasRuntime": false,
"info": Array [
"Rollup aggregations:",
"terms",
],
"isMapped": false,
"kbnType": undefined,
"name": "Elastic",
"searchable": true,
"type": "keyword",
},
Object {
"displayName": "timestamp",
"esTypes": Array [
"date",
],
"excluded": false,
"format": "",
"hasRuntime": false,
"info": Array [
"Rollup aggregations:",
"date_histogram (interval: 30s, delay: 30s, UTC)",
],
"isMapped": false,
"kbnType": undefined,
"name": "timestamp",
"type": "date",
},
Object {
"displayName": "conflictingField",
"esTypes": Array [
"keyword",
"long",
],
"excluded": false,
"format": "",
"hasRuntime": false,
"info": Array [],
"isMapped": false,
"kbnType": undefined,
"name": "conflictingField",
"type": "keyword, long",
},
Object {
"displayName": "amount",
"esTypes": Array [
"long",
],
"excluded": false,
"format": "",
"hasRuntime": false,
"info": Array [
"Rollup aggregations:",
"histogram (interval: 5)",
"avg",
"max",
"min",
"sum",
"value_count",
],
"isMapped": false,
"kbnType": undefined,
"name": "amount",
"type": "long",
},
]
}
/>
</div>
`;
exports[`IndexedFieldsTable should filter based on the query bar 1`] = `
<div>
<Table
@ -124,6 +267,20 @@ exports[`IndexedFieldsTable should render normally 1`] = `
"name": "conflictingField",
"type": "keyword, long",
},
Object {
"displayName": "amount",
"esTypes": Array [
"long",
],
"excluded": false,
"format": "",
"hasRuntime": false,
"info": Array [],
"isMapped": false,
"kbnType": undefined,
"name": "amount",
"type": "long",
},
]
}
/>

View file

@ -8,13 +8,13 @@
import React from 'react';
import { shallow } from 'enzyme';
import { IIndexPattern } from 'src/plugins/data/public';
import { IndexPattern } from 'src/plugins/data/public';
import { IndexedFieldItem } from '../../types';
import { Table, renderFieldName } from './table';
const indexPattern = {
timeFieldName: 'timestamp',
} as IIndexPattern;
} as IndexPattern;
const items: IndexedFieldItem[] = [
{

View file

@ -8,8 +8,9 @@
import React from 'react';
import { shallow } from 'enzyme';
import { IndexPatternField, IndexPattern } from 'src/plugins/data/public';
import { IndexPatternField, IndexPattern, IndexPatternType } from 'src/plugins/data/public';
import { IndexedFieldsTable } from './indexed_fields_table';
import { RollupIndexPatternListConfig } from '../../../service/list';
jest.mock('@elastic/eui', () => ({
EuiFlexGroup: 'eui-flex-group',
@ -28,7 +29,8 @@ jest.mock('./components/table', () => ({
const helpers = {
editField: (fieldName: string) => {},
deleteField: (fieldName: string) => {},
getFieldInfo: () => [],
// getFieldInfo handles non rollups as well
getFieldInfo: new RollupIndexPatternListConfig().getFieldInfo,
};
const indexPattern = ({
@ -36,6 +38,34 @@ const indexPattern = ({
getFormatterForFieldNoDefault: () => ({ params: () => ({}) }),
} as unknown) as IndexPattern;
const rollupIndexPattern = ({
type: IndexPatternType.ROLLUP,
typeMeta: {
params: {
'rollup-index': 'rollup',
},
aggs: {
date_histogram: {
timestamp: {
agg: 'date_histogram',
fixed_interval: '30s',
delay: '30s',
time_zone: 'UTC',
},
},
terms: { Elastic: { agg: 'terms' } },
histogram: { amount: { agg: 'histogram', interval: 5 } },
avg: { amount: { agg: 'avg' } },
max: { amount: { agg: 'max' } },
min: { amount: { agg: 'min' } },
sum: { amount: { agg: 'sum' } },
value_count: { amount: { agg: 'value_count' } },
},
},
getNonScriptedFields: () => fields,
getFormatterForFieldNoDefault: () => ({ params: () => ({}) }),
} as unknown) as IndexPattern;
const mockFieldToIndexPatternField = (
spec: Record<string, string | string[] | boolean | undefined>
) => {
@ -51,6 +81,7 @@ const fields = [
},
{ name: 'timestamp', displayName: 'timestamp', esTypes: ['date'] },
{ name: 'conflictingField', displayName: 'conflictingField', esTypes: ['keyword', 'long'] },
{ name: 'amount', displayName: 'amount', esTypes: ['long'] },
].map(mockFieldToIndexPatternField);
describe('IndexedFieldsTable', () => {
@ -115,4 +146,26 @@ describe('IndexedFieldsTable', () => {
expect(component).toMatchSnapshot();
});
describe('IndexedFieldsTable with rollup index pattern', () => {
test('should render normally', async () => {
const component = shallow(
<IndexedFieldsTable
fields={fields}
indexPattern={rollupIndexPattern}
helpers={helpers}
fieldWildcardMatcher={() => {
return () => false;
}}
indexedFieldTypeFilter=""
fieldFilter=""
/>
);
await new Promise((resolve) => process.nextTick(resolve));
component.update();
expect(component).toMatchSnapshot();
});
});
});

View file

@ -8,7 +8,7 @@
import React, { Component } from 'react';
import { createSelector } from 'reselect';
import { IndexPatternField, IndexPattern, IFieldType } from '../../../../../../plugins/data/public';
import { IndexPatternField, IndexPattern } from '../../../../../../plugins/data/public';
import { Table } from './components/table';
import { IndexedFieldItem } from './types';
@ -20,7 +20,7 @@ interface IndexedFieldsTableProps {
helpers: {
editField: (fieldName: string) => void;
deleteField: (fieldName: string) => void;
getFieldInfo: (indexPattern: IndexPattern, field: IFieldType) => string[];
getFieldInfo: (indexPattern: IndexPattern, field: IndexPatternField) => string[];
};
fieldWildcardMatcher: (filters: any[]) => (val: any) => boolean;
}

View file

@ -7,8 +7,7 @@
*/
import { i18n } from '@kbn/i18n';
import { IIndexPattern, IFieldType } from 'src/plugins/data/public';
import { SimpleSavedObject } from 'src/core/public';
import { IndexPattern, IndexPatternField, IndexPatternType } from '../../../../data/public';
export interface IndexPatternTag {
key: string;
@ -23,12 +22,9 @@ const defaultIndexPatternListName = i18n.translate(
);
export class IndexPatternListConfig {
public readonly key = 'default';
public readonly key: IndexPatternType = IndexPatternType.DEFAULT;
public getIndexPatternTags(
indexPattern: IIndexPattern | SimpleSavedObject<IIndexPattern>,
isDefault: boolean
): IndexPatternTag[] {
public getIndexPatternTags(indexPattern: IndexPattern, isDefault: boolean): IndexPatternTag[] {
return isDefault
? [
{
@ -39,11 +35,11 @@ export class IndexPatternListConfig {
: [];
}
public getFieldInfo(indexPattern: IIndexPattern, field: IFieldType): string[] {
public getFieldInfo(indexPattern: IndexPattern, field: IndexPatternField): string[] {
return [];
}
public areScriptedFieldsEnabled(indexPattern: IIndexPattern): boolean {
public areScriptedFieldsEnabled(indexPattern: IndexPattern): boolean {
return true;
}
}

View file

@ -6,13 +6,11 @@
* Side Public License, v 1.
*/
import { IIndexPattern, IFieldType } from 'src/plugins/data/public';
import { SimpleSavedObject } from 'src/core/public';
import { IndexPattern, IndexPatternField } from 'src/plugins/data/public';
import { once } from 'lodash';
import { CoreStart } from '../../../../../core/public';
import { IndexPatternListConfig, IndexPatternTag } from './config';
import { CONFIG_ROLLUPS } from '../../constants';
// @ts-ignore
import { RollupIndexPatternListConfig } from './rollup_list_config';
interface IndexPatternListManagerStart {
@ -32,10 +30,7 @@ export class IndexPatternListManager {
return configs;
});
return {
getIndexPatternTags: (
indexPattern: IIndexPattern | SimpleSavedObject<IIndexPattern>,
isDefault: boolean
) =>
getIndexPatternTags: (indexPattern: IndexPattern, isDefault: boolean) =>
getConfigs().reduce(
(tags: IndexPatternTag[], config) =>
config.getIndexPatternTags
@ -44,14 +39,14 @@ export class IndexPatternListManager {
[]
),
getFieldInfo: (indexPattern: IIndexPattern, field: IFieldType): string[] =>
getFieldInfo: (indexPattern: IndexPattern, field: IndexPatternField): string[] =>
getConfigs().reduce(
(info: string[], config) =>
config.getFieldInfo ? info.concat(config.getFieldInfo(indexPattern, field)) : info,
[]
),
areScriptedFieldsEnabled: (indexPattern: IIndexPattern): boolean =>
areScriptedFieldsEnabled: (indexPattern: IndexPattern): boolean =>
getConfigs().every((config) =>
config.areScriptedFieldsEnabled ? config.areScriptedFieldsEnabled(indexPattern) : true
),

View file

@ -6,18 +6,17 @@
* Side Public License, v 1.
*/
import { IndexPattern, IndexPatternField, IndexPatternType } from '../../../../data/public';
import { IndexPatternListConfig } from '.';
function isRollup(indexPattern) {
return (
indexPattern.type === 'rollup' || (indexPattern.get && indexPattern.get('type') === 'rollup')
);
function isRollup(indexPattern: IndexPattern) {
return indexPattern.type === IndexPatternType.ROLLUP;
}
export class RollupIndexPatternListConfig extends IndexPatternListConfig {
key = 'rollup';
key = IndexPatternType.ROLLUP;
getIndexPatternTags = (indexPattern) => {
getIndexPatternTags = (indexPattern: IndexPattern) => {
return isRollup(indexPattern)
? [
{
@ -28,13 +27,13 @@ export class RollupIndexPatternListConfig extends IndexPatternListConfig {
: [];
};
getFieldInfo = (indexPattern, field) => {
getFieldInfo = (indexPattern: IndexPattern, field: IndexPatternField) => {
if (!isRollup(indexPattern)) {
return [];
}
const allAggs = indexPattern.typeMeta && indexPattern.typeMeta.aggs;
const fieldAggs = allAggs && Object.keys(allAggs).filter((agg) => allAggs[agg][field]);
const fieldAggs = allAggs && Object.keys(allAggs).filter((agg) => allAggs[agg][field.name]);
if (!fieldAggs || !fieldAggs.length) {
return [];
@ -42,13 +41,12 @@ export class RollupIndexPatternListConfig extends IndexPatternListConfig {
return ['Rollup aggregations:'].concat(
fieldAggs.map((aggName) => {
const agg = allAggs[aggName][field];
const agg = allAggs![aggName][field.name];
switch (aggName) {
case 'date_histogram':
return `${aggName} (interval: ${agg.interval}, ${
return `${aggName} (interval: ${agg.fixed_interval}, ${
agg.delay ? `delay: ${agg.delay},` : ''
} ${agg.time_zone})`;
break;
case 'histogram':
return `${aggName} (interval: ${agg.interval})`;
default:
@ -58,7 +56,7 @@ export class RollupIndexPatternListConfig extends IndexPatternListConfig {
);
};
areScriptedFieldsEnabled = (indexPattern) => {
areScriptedFieldsEnabled = (indexPattern: IndexPattern) => {
return !isRollup(indexPattern);
};
}