Skip to content

Commit d000243

Browse files
ppisljardej611kibanamachine
authored andcommitted
[Lens as Code] metric chart schema and transformations (elastic#233813)
## Summary resolves elastic#233657 resolves elastic#233659 --------- Co-authored-by: Marco Liberati <[email protected]> Co-authored-by: kibanamachine <[email protected]>
1 parent f782092 commit d000243

File tree

17 files changed

+1199
-111
lines changed

17 files changed

+1199
-111
lines changed

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/config_builder.ts

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ import {
2020
buildTable,
2121
buildXY,
2222
buildPartitionChart,
23-
fromMetricLegacyToAPI,
2423
} from './charts';
24+
import { fromAPItoLensState, fromLensStateToAPI } from './transforms/charts/metric';
2525
import type { LensApiState } from './schema';
2626
import { isLensLegacyFormat } from './utils';
2727

@@ -43,13 +43,13 @@ export class LensConfigBuilder {
4343
};
4444

4545
private apiConvertersByChart = {
46-
metric: fromMetricLegacyToAPI,
46+
metric: { fromAPItoLensState, fromLensStateToAPI },
4747
};
4848
private formulaAPI: FormulaPublicApi | undefined;
49-
private dataViewsAPI: DataViewsCommon;
49+
private dataViewsAPI: DataViewsCommon | undefined;
5050

5151
// formulaApi is optional, as it is not necessary to use it when creating charts with ES|QL
52-
constructor(dataViewsAPI: DataViewsCommon, formulaAPI?: FormulaPublicApi) {
52+
constructor(dataViewsAPI?: DataViewsCommon, formulaAPI?: FormulaPublicApi) {
5353
this.formulaAPI = formulaAPI;
5454
this.dataViewsAPI = dataViewsAPI;
5555
}
@@ -64,6 +64,10 @@ export class LensConfigBuilder {
6464
config: LensConfig | LensApiState,
6565
options: LensConfigOptions = {}
6666
): Promise<LensAttributes | LensEmbeddableInput> {
67+
if (!this.dataViewsAPI) {
68+
throw new Error('DataViews API is required to build Lens configurations');
69+
}
70+
6771
const chartType = isLensLegacyFormat(config) ? config.chartType : config.type;
6872
const chartBuilderFn = this.charts[chartType];
6973
const chartConfig = await chartBuilderFn(config as any, {
@@ -92,14 +96,21 @@ export class LensConfigBuilder {
9296
return chartState as LensAttributes;
9397
}
9498

95-
async toAPIFormat(config: LensAttributes): Promise<LensApiState> {
96-
const chartType = config.visualizationType;
99+
fromAPIFormat(config: LensApiState): LensAttributes {
100+
// Currently we only support metric conversion from API to attributes
101+
const chartType = config.type;
97102
if (chartType === 'metric') {
98103
const converter = this.apiConvertersByChart[chartType];
99-
return converter(config, {
100-
formulaAPI: this.formulaAPI,
101-
dataViewsAPI: this.dataViewsAPI,
102-
});
104+
return converter.fromAPItoLensState(config);
105+
}
106+
throw new Error(`No attributes converter found for chart type: ${chartType}`);
107+
}
108+
109+
toAPIFormat(config: LensAttributes): LensApiState {
110+
const chartType = config.visualizationType;
111+
if (chartType === 'lnsMetric') {
112+
const converter = this.apiConvertersByChart.metric;
113+
return converter.fromLensStateToAPI(config);
103114
}
104115
throw new Error(`No API converter found for chart type: ${chartType}`);
105116
}

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/charts/metric.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@ describe('Metric Schema', () => {
331331
query: 'FROM my-index | LIMIT 100',
332332
},
333333
metric: {
334+
operation: 'value',
334335
column: 'unique_count' as const,
335336
fit: false,
336337
alignments: { labels: 'left', value: 'left' },

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/charts/metric.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
uniqueCountMetricOperationSchema,
2626
sumMetricOperationSchema,
2727
esqlColumnSchema,
28+
genericOperationOptionsSchema,
2829
} from '../metric_ops';
2930
import { coloringTypeSchema } from '../color';
3031
import { datasetSchema, datasetEsqlTableSchema } from '../dataset';
@@ -250,12 +251,20 @@ const esqlMetricState = schema.object({
250251
/**
251252
* Primary value configuration, must define operation.
252253
*/
253-
metric: schema.allOf([metricStatePrimaryMetricOptionsSchema, esqlColumnSchema]),
254+
metric: schema.allOf([
255+
schema.object(genericOperationOptionsSchema),
256+
metricStatePrimaryMetricOptionsSchema,
257+
esqlColumnSchema,
258+
]),
254259
/**
255260
* Secondary value configuration, must define operation.
256261
*/
257262
secondary_metric: schema.maybe(
258-
schema.allOf([metricStateSecondaryMetricOptionsSchema, esqlColumnSchema])
263+
schema.allOf([
264+
schema.object(genericOperationOptionsSchema),
265+
metricStateSecondaryMetricOptionsSchema,
266+
esqlColumnSchema,
267+
])
259268
),
260269
/**
261270
* Configure how to break down the metric (e.g. show one metric per term).
@@ -266,3 +275,5 @@ const esqlMetricState = schema.object({
266275
export const metricStateSchema = schema.oneOf([metricStateSchemaNoESQL, esqlMetricState]);
267276

268277
export type MetricState = TypeOf<typeof metricStateSchema>;
278+
export type MetricStateNoESQL = TypeOf<typeof metricStateSchemaNoESQL>;
279+
export type MetricStateESQL = TypeOf<typeof esqlMetricState>;

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/dataset.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* License v3.0 only", or the "Server Side Public License, v 1".
88
*/
99

10-
import { schema } from '@kbn/config-schema';
10+
import { schema, type TypeOf } from '@kbn/config-schema';
1111

1212
export const datasetTypeSchema = schema.oneOf([
1313
// DataView dataset type
@@ -134,3 +134,6 @@ export const datasetEsqlTableTypeSchema = schema.oneOf([
134134
export const datasetEsqlTableSchema = {
135135
dataset: datasetEsqlTableTypeSchema,
136136
};
137+
138+
const anyDatasetSchema = schema.oneOf([datasetTypeSchema, datasetEsqlTableTypeSchema]);
139+
export type DatasetType = TypeOf<typeof anyDatasetSchema>;

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ export const lensApiStateSchema = schema.oneOf([metricStateSchema]);
1616

1717
export type LensApiState = typeof lensApiStateSchema.type;
1818

19-
export type { MetricState } from './charts/metric';
19+
export type { MetricState, metricStateSchemaNoESQL } from './charts/metric';
2020

2121
export type NarrowByType<T, U> = T extends { type: U } ? T : never;
2222

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/metric_ops.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ describe('Metric Operations Schemas', () => {
3535
describe('columnValueOperationSchema', () => {
3636
it('validates a valid metric operation configuration', () => {
3737
const input = {
38+
operation: 'value',
3839
column: 'sum' as const,
3940
};
4041

src/platform/packages/shared/kbn-lens-embeddable-utils/config_builder/schema/metric_ops.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
} from './constants';
2020
import { LENS_EMPTY_AS_NULL_DEFAULT_VALUE } from '../transforms/columns/utils';
2121

22-
const genericOperationOptionsSchema = {
22+
export const genericOperationOptionsSchema = {
2323
...formatSchema,
2424
/**
2525
* Label for the operation
@@ -64,6 +64,7 @@ export const esqlColumnSchema = schema.object({
6464
/**
6565
* Value
6666
*/
67+
operation: schema.literal('value'),
6768
column: schema.string({
6869
meta: {
6970
description: 'Column to use',

0 commit comments

Comments
 (0)