Skip to content

Commit ad5c116

Browse files
[TSVB] Allow custom label for fields via index pattern field management (elastic#84612)
* [TSVB] Allow custom label for fields via index pattern field management Closes: elastic#84336 * replace saveObject, elasticsearch client to new one * fix CI * update schema * fix Top Hit * some changes * partially move getting fields into client side * fix PR comments * fix issue with getting fields * move SanitizedFieldType to common types * fix issue on changing index pattern * fix issue * fix regression * some work * remove extractFieldName, createCustomLabelSelectHandler * request/response processors should be async * some work * remove tests for createCustomLabelSelectHandler * fix table * fix placeholder * some work * fix jest * fix CI * fix label for table view * test: visualize app visual builder switch index patterns should be able to switch between index patterns * fix functional tests * fix sorting * fix labels for entire timerange mode * add createFieldsFetcher method * table view - fix pivot label * fix PR comments * fix issue with selecting buckets scripts * fix types * Update create_select_handler.test.ts * fix PR comments Co-authored-by: Kibana Machine <[email protected]>
1 parent db28909 commit ad5c116

File tree

108 files changed

+980
-699
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

108 files changed

+980
-699
lines changed

src/plugins/vis_type_timeseries/common/__snapshots__/model_options.test.js.snap

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/plugins/vis_type_timeseries/common/agg_lookup.test.js renamed to src/plugins/vis_type_timeseries/common/agg_lookup.test.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,15 @@
1818
*/
1919

2020
import { isBasicAgg } from './agg_lookup';
21+
import { MetricsItemsSchema } from './types';
2122

2223
describe('aggLookup', () => {
2324
describe('isBasicAgg(metric)', () => {
2425
test('returns true for a basic metric (count)', () => {
25-
expect(isBasicAgg({ type: 'count' })).toEqual(true);
26+
expect(isBasicAgg({ type: 'count' } as MetricsItemsSchema)).toEqual(true);
2627
});
2728
test('returns false for a pipeline metric (derivative)', () => {
28-
expect(isBasicAgg({ type: 'derivative' })).toEqual(false);
29+
expect(isBasicAgg({ type: 'derivative' } as MetricsItemsSchema)).toEqual(false);
2930
});
3031
});
3132
});

src/plugins/vis_type_timeseries/common/agg_lookup.js renamed to src/plugins/vis_type_timeseries/common/agg_lookup.ts

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,11 @@
1717
* under the License.
1818
*/
1919

20-
import _ from 'lodash';
20+
import { omit, pick, includes } from 'lodash';
2121
import { i18n } from '@kbn/i18n';
22+
import { MetricsItemsSchema } from './types';
2223

23-
export const lookup = {
24+
export const lookup: Record<string, string> = {
2425
count: i18n.translate('visTypeTimeseries.aggLookup.countLabel', { defaultMessage: 'Count' }),
2526
calculation: i18n.translate('visTypeTimeseries.aggLookup.calculationLabel', {
2627
defaultMessage: 'Calculation',
@@ -122,11 +123,11 @@ const pipeline = [
122123

123124
const byType = {
124125
_all: lookup,
125-
pipeline: pipeline,
126-
basic: _.omit(lookup, pipeline),
127-
metrics: _.pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']),
126+
pipeline,
127+
basic: omit(lookup, pipeline),
128+
metrics: pick(lookup, ['count', 'avg', 'min', 'max', 'sum', 'cardinality', 'value_count']),
128129
};
129130

130-
export function isBasicAgg(item) {
131-
return _.includes(Object.keys(byType.basic), item.type);
131+
export function isBasicAgg(item: MetricsItemsSchema) {
132+
return includes(Object.keys(byType.basic), item.type);
132133
}

src/plugins/vis_type_timeseries/common/calculate_label.test.js renamed to src/plugins/vis_type_timeseries/common/calculate_label.test.ts

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,66 +18,79 @@
1818
*/
1919

2020
import { calculateLabel } from './calculate_label';
21+
import type { MetricsItemsSchema } from './types';
2122

2223
describe('calculateLabel(metric, metrics)', () => {
23-
test('returns "Unknown" for empty metric', () => {
24-
expect(calculateLabel()).toEqual('Unknown');
25-
});
26-
2724
test('returns the metric.alias if set', () => {
28-
expect(calculateLabel({ alias: 'Example' })).toEqual('Example');
25+
expect(calculateLabel({ alias: 'Example' } as MetricsItemsSchema)).toEqual('Example');
2926
});
3027

3128
test('returns "Count" for a count metric', () => {
32-
expect(calculateLabel({ type: 'count' })).toEqual('Count');
29+
expect(calculateLabel({ type: 'count' } as MetricsItemsSchema)).toEqual('Count');
3330
});
3431

3532
test('returns "Calculation" for a bucket script metric', () => {
36-
expect(calculateLabel({ type: 'calculation' })).toEqual('Bucket Script');
33+
expect(calculateLabel({ type: 'calculation' } as MetricsItemsSchema)).toEqual('Bucket Script');
3734
});
3835

39-
test('returns formated label for series_agg', () => {
40-
const label = calculateLabel({ type: 'series_agg', function: 'max' });
36+
test('returns formatted label for series_agg', () => {
37+
const label = calculateLabel({ type: 'series_agg', function: 'max' } as MetricsItemsSchema);
38+
4139
expect(label).toEqual('Series Agg (max)');
4240
});
4341

44-
test('returns formated label for basic aggs', () => {
45-
const label = calculateLabel({ type: 'avg', field: 'memory' });
42+
test('returns formatted label for basic aggs', () => {
43+
const label = calculateLabel({ type: 'avg', field: 'memory' } as MetricsItemsSchema);
44+
4645
expect(label).toEqual('Average of memory');
4746
});
4847

49-
test('returns formated label for pipeline aggs', () => {
50-
const metric = { id: 2, type: 'derivative', field: 1 };
51-
const metrics = [{ id: 1, type: 'max', field: 'network.out.bytes' }, metric];
48+
test('returns formatted label for pipeline aggs', () => {
49+
const metric = ({ id: 2, type: 'derivative', field: 1 } as unknown) as MetricsItemsSchema;
50+
const metrics = ([
51+
{ id: 1, type: 'max', field: 'network.out.bytes' },
52+
metric,
53+
] as unknown) as MetricsItemsSchema[];
5254
const label = calculateLabel(metric, metrics);
55+
5356
expect(label).toEqual('Derivative of Max of network.out.bytes');
5457
});
5558

56-
test('returns formated label for derivative of percentile', () => {
57-
const metric = { id: 2, type: 'derivative', field: '1[50.0]' };
58-
const metrics = [{ id: 1, type: 'percentile', field: 'network.out.bytes' }, metric];
59+
test('returns formatted label for derivative of percentile', () => {
60+
const metric = ({
61+
id: 2,
62+
type: 'derivative',
63+
field: '1[50.0]',
64+
} as unknown) as MetricsItemsSchema;
65+
const metrics = ([
66+
{ id: 1, type: 'percentile', field: 'network.out.bytes' },
67+
metric,
68+
] as unknown) as MetricsItemsSchema[];
5969
const label = calculateLabel(metric, metrics);
70+
6071
expect(label).toEqual('Derivative of Percentile of network.out.bytes (50.0)');
6172
});
6273

63-
test('returns formated label for pipeline aggs (deep)', () => {
64-
const metric = { id: 3, type: 'derivative', field: 2 };
65-
const metrics = [
74+
test('returns formatted label for pipeline aggs (deep)', () => {
75+
const metric = ({ id: 3, type: 'derivative', field: 2 } as unknown) as MetricsItemsSchema;
76+
const metrics = ([
6677
{ id: 1, type: 'max', field: 'network.out.bytes' },
6778
{ id: 2, type: 'moving_average', field: 1 },
6879
metric,
69-
];
80+
] as unknown) as MetricsItemsSchema[];
7081
const label = calculateLabel(metric, metrics);
82+
7183
expect(label).toEqual('Derivative of Moving Average of Max of network.out.bytes');
7284
});
7385

74-
test('returns formated label for pipeline aggs uses alias for field metric', () => {
75-
const metric = { id: 2, type: 'derivative', field: 1 };
76-
const metrics = [
86+
test('returns formatted label for pipeline aggs uses alias for field metric', () => {
87+
const metric = ({ id: 2, type: 'derivative', field: 1 } as unknown) as MetricsItemsSchema;
88+
const metrics = ([
7789
{ id: 1, type: 'max', field: 'network.out.bytes', alias: 'Outbound Traffic' },
7890
metric,
79-
];
91+
] as unknown) as MetricsItemsSchema[];
8092
const label = calculateLabel(metric, metrics);
93+
8194
expect(label).toEqual('Derivative of Outbound Traffic');
8295
});
8396
});

src/plugins/vis_type_timeseries/common/calculate_label.js renamed to src/plugins/vis_type_timeseries/common/calculate_label.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@
1818
*/
1919

2020
import { includes, startsWith } from 'lodash';
21-
import { lookup } from './agg_lookup';
2221
import { i18n } from '@kbn/i18n';
22+
import { lookup } from './agg_lookup';
23+
import { MetricsItemsSchema, SanitizedFieldType } from './types';
2324

2425
const paths = [
2526
'cumulative_sum',
@@ -36,7 +37,15 @@ const paths = [
3637
'positive_only',
3738
];
3839

39-
export function calculateLabel(metric, metrics) {
40+
export const extractFieldLabel = (fields: SanitizedFieldType[], name: string) => {
41+
return fields.find((f) => f.name === name)?.label ?? name;
42+
};
43+
44+
export const calculateLabel = (
45+
metric: MetricsItemsSchema,
46+
metrics: MetricsItemsSchema[] = [],
47+
fields: SanitizedFieldType[] = []
48+
): string => {
4049
if (!metric) {
4150
return i18n.translate('visTypeTimeseries.calculateLabel.unknownLabel', {
4251
defaultMessage: 'Unknown',
@@ -73,7 +82,7 @@ export function calculateLabel(metric, metrics) {
7382
if (metric.type === 'positive_rate') {
7483
return i18n.translate('visTypeTimeseries.calculateLabel.positiveRateLabel', {
7584
defaultMessage: 'Counter Rate of {field}',
76-
values: { field: metric.field },
85+
values: { field: extractFieldLabel(fields, metric.field!) },
7786
});
7887
}
7988
if (metric.type === 'static') {
@@ -84,15 +93,15 @@ export function calculateLabel(metric, metrics) {
8493
}
8594

8695
if (includes(paths, metric.type)) {
87-
const targetMetric = metrics.find((m) => startsWith(metric.field, m.id));
88-
const targetLabel = calculateLabel(targetMetric, metrics);
96+
const targetMetric = metrics.find((m) => startsWith(metric.field!, m.id));
97+
const targetLabel = calculateLabel(targetMetric!, metrics, fields);
8998

9099
// For percentiles we need to parse the field id to extract the percentile
91100
// the user configured in the percentile aggregation and specified in the
92101
// submetric they selected. This applies only to pipeline aggs.
93102
if (targetMetric && targetMetric.type === 'percentile') {
94103
const percentileValueMatch = /\[([0-9\.]+)\]$/;
95-
const matches = metric.field.match(percentileValueMatch);
104+
const matches = metric.field!.match(percentileValueMatch);
96105
if (matches) {
97106
return i18n.translate(
98107
'visTypeTimeseries.calculateLabel.lookupMetricTypeOfTargetWithAdditionalLabel',
@@ -115,6 +124,9 @@ export function calculateLabel(metric, metrics) {
115124

116125
return i18n.translate('visTypeTimeseries.calculateLabel.lookupMetricTypeOfMetricFieldRankLabel', {
117126
defaultMessage: '{lookupMetricType} of {metricField}',
118-
values: { lookupMetricType: lookup[metric.type], metricField: metric.field },
127+
values: {
128+
lookupMetricType: lookup[metric.type],
129+
metricField: extractFieldLabel(fields, metric.field!),
130+
},
119131
});
120-
}
132+
};

src/plugins/vis_type_timeseries/common/extract_index_patterns.test.js renamed to src/plugins/vis_type_timeseries/common/extract_index_patterns.test.ts

Lines changed: 5 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,13 @@
1818
*/
1919

2020
import { extractIndexPatterns } from './extract_index_patterns';
21+
import { PanelSchema } from './types';
2122

2223
describe('extractIndexPatterns(vis)', () => {
23-
let visParams;
24-
let visFields;
24+
let panel: PanelSchema;
2525

2626
beforeEach(() => {
27-
visFields = {
28-
'*': [],
29-
};
30-
visParams = {
27+
panel = {
3128
index_pattern: '*',
3229
series: [
3330
{
@@ -40,25 +37,10 @@ describe('extractIndexPatterns(vis)', () => {
4037
},
4138
],
4239
annotations: [{ index_pattern: 'notes-*' }, { index_pattern: 'example-1-*' }],
43-
};
40+
} as PanelSchema;
4441
});
4542

4643
test('should return index patterns', () => {
47-
visFields = {};
48-
49-
expect(extractIndexPatterns(visParams, visFields)).toEqual([
50-
'*',
51-
'example-1-*',
52-
'example-2-*',
53-
'notes-*',
54-
]);
55-
});
56-
57-
test('should return index patterns that do not exist in visFields', () => {
58-
expect(extractIndexPatterns(visParams, visFields)).toEqual([
59-
'example-1-*',
60-
'example-2-*',
61-
'notes-*',
62-
]);
44+
expect(extractIndexPatterns(panel, '')).toEqual(['*', 'example-1-*', 'example-2-*', 'notes-*']);
6345
});
6446
});

src/plugins/vis_type_timeseries/common/extract_index_patterns.js renamed to src/plugins/vis_type_timeseries/common/extract_index_patterns.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,33 +17,37 @@
1717
* under the License.
1818
*/
1919
import { uniq } from 'lodash';
20+
import { PanelSchema } from '../common/types';
2021

21-
export function extractIndexPatterns(panel, excludedFields = {}) {
22-
const patterns = [];
22+
export function extractIndexPatterns(
23+
panel: PanelSchema,
24+
defaultIndex?: PanelSchema['default_index_pattern']
25+
) {
26+
const patterns: string[] = [];
2327

24-
if (!excludedFields[panel.index_pattern]) {
28+
if (panel.index_pattern) {
2529
patterns.push(panel.index_pattern);
2630
}
2731

2832
panel.series.forEach((series) => {
2933
const indexPattern = series.series_index_pattern;
30-
if (indexPattern && series.override_index_pattern && !excludedFields[indexPattern]) {
34+
if (indexPattern && series.override_index_pattern) {
3135
patterns.push(indexPattern);
3236
}
3337
});
3438

3539
if (panel.annotations) {
3640
panel.annotations.forEach((item) => {
3741
const indexPattern = item.index_pattern;
38-
if (indexPattern && !excludedFields[indexPattern]) {
42+
if (indexPattern) {
3943
patterns.push(indexPattern);
4044
}
4145
});
4246
}
4347

44-
if (patterns.length === 0) {
45-
patterns.push('');
48+
if (patterns.length === 0 && defaultIndex) {
49+
patterns.push(defaultIndex);
4650
}
4751

48-
return uniq(patterns).sort();
52+
return uniq<string>(patterns).sort();
4953
}

src/plugins/vis_type_timeseries/common/field_types.js renamed to src/plugins/vis_type_timeseries/common/field_types.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
* under the License.
1818
*/
1919

20-
export const FIELD_TYPES = {
21-
BOOLEAN: 'boolean',
22-
DATE: 'date',
23-
GEO: 'geo_point',
24-
NUMBER: 'number',
25-
STRING: 'string',
26-
};
20+
export enum FIELD_TYPES {
21+
BOOLEAN = 'boolean',
22+
DATE = 'date',
23+
GEO = 'geo_point',
24+
NUMBER = 'number',
25+
STRING = 'string',
26+
}

src/plugins/vis_type_timeseries/common/model_options.js renamed to src/plugins/vis_type_timeseries/common/model_options.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,10 @@
1717
* under the License.
1818
*/
1919

20-
export const MODEL_TYPES = {
21-
UNWEIGHTED: 'simple',
22-
WEIGHTED_EXPONENTIAL: 'ewma',
23-
WEIGHTED_EXPONENTIAL_DOUBLE: 'holt',
24-
WEIGHTED_EXPONENTIAL_TRIPLE: 'holt_winters',
25-
WEIGHTED_LINEAR: 'linear',
26-
};
20+
export enum MODEL_TYPES {
21+
UNWEIGHTED = 'simple',
22+
WEIGHTED_EXPONENTIAL = 'ewma',
23+
WEIGHTED_EXPONENTIAL_DOUBLE = 'holt',
24+
WEIGHTED_EXPONENTIAL_TRIPLE = 'holt_winters',
25+
WEIGHTED_LINEAR = 'linear',
26+
}

src/plugins/vis_type_timeseries/common/timerange_data_modes.js renamed to src/plugins/vis_type_timeseries/common/timerange_data_modes.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,19 @@
2222
* @constant
2323
* @public
2424
*/
25-
export const TIME_RANGE_DATA_MODES = {
25+
export enum TIME_RANGE_DATA_MODES {
2626
/**
2727
* Entire timerange mode will match all the documents selected in the
2828
* timerange timepicker
2929
*/
30-
ENTIRE_TIME_RANGE: 'entire_time_range',
30+
ENTIRE_TIME_RANGE = 'entire_time_range',
3131

3232
/**
3333
* Last value mode will match only the documents for the specified interval
3434
* from the end of the timerange.
3535
*/
36-
LAST_VALUE: 'last_value',
37-
};
36+
LAST_VALUE = 'last_value',
37+
}
3838

3939
/**
4040
* Key for getting the Time Range mode from the Panel configuration object.

0 commit comments

Comments
 (0)