mirror of
https://github.com/elastic/kibana.git
synced 2025-04-23 17:28:26 -04:00
[Step 3] VisEditors Telemetry enhancements (add new agg-based and lens telemetries) (#135615)
* initial comit * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * push chart_expressions logic * update tests * fix JEST * push some telemetries * fix some cases * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * update tests * add some lens part * add handlers.logRenderTelemetry method * visGroup -> originatingApp * remove visTpe, extra, onlyExtra * remove handlers.logRenderTelemetry from handlers * remove context from snapshots * [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' * add lens operations telemetry * fix heaatmap, vislib * push some telemetries * cleanup * push some logic * fix merge conflicts * push some logic * add lens map telemetry * add render_lens_vis_cases * add render_lens_vis_observability_exploratory_view * cleanup * cleanup * make getRenderEventCounters optional * add summary_row and color_by_value telemetries * try to fix double rendering * update xy telemetries * fix TSVB * fix lens * fix Timelion * add mixed_xy telemetry * [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' * Update x-pack/plugins/observability/public/components/shared/exploratory_view/lens_embeddable.tsx Co-authored-by: Shahzad <shahzad31comp@gmail.com> * Update x-pack/plugins/observability/public/components/shared/exploratory_view/embeddable/embeddable.tsx Co-authored-by: Shahzad <shahzad31comp@gmail.com> * Update expression_renderer.tsx * update originatingApp * Update expression_renderer.tsx * add JEST for core changes * Update plugin.ts * Update src/plugins/expressions/common/expression_renderers/types.ts Co-authored-by: Michael Dokolin <dokmic@gmail.com> * fix PR comments * add renderComplete param to VisualizationContainer * fix mixed_xy issue Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Co-authored-by: Shahzad <shahzad31comp@gmail.com> Co-authored-by: Michael Dokolin <dokmic@gmail.com>
This commit is contained in:
parent
7a153139cf
commit
d4bb959bea
120 changed files with 1566 additions and 415 deletions
|
@ -18,13 +18,16 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
|
||||
const value = new ExecutionContextContainer(context).toHeader();
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22description%22%3A%22test-descripton%22%7D",
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22meta%22%3A%7B%22foo%22%3A%22test%22%7D%2C%22description%22%3A%22test-descripton%22%7D",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -34,6 +37,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'child-test-type',
|
||||
name: 'child-test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: true,
|
||||
},
|
||||
description: 'child-test-descripton',
|
||||
};
|
||||
|
||||
|
@ -48,7 +54,7 @@ describe('KibanaExecutionContext', () => {
|
|||
const value = new ExecutionContextContainer(context).toHeader();
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"x-kbn-context": "%7B%22type%22%3A%22type%22%2C%22name%22%3A%22name%22%2C%22id%22%3A%2241%22%2C%22description%22%3A%22descripton%22%2C%22child%22%3A%7B%22type%22%3A%22child-test-type%22%2C%22name%22%3A%22child-test-name%22%2C%22id%22%3A%2242%22%2C%22description%22%3A%22child-test-descripton%22%7D%7D",
|
||||
"x-kbn-context": "%7B%22type%22%3A%22type%22%2C%22name%22%3A%22name%22%2C%22id%22%3A%2241%22%2C%22description%22%3A%22descripton%22%2C%22child%22%3A%7B%22type%22%3A%22child-test-type%22%2C%22name%22%3A%22child-test-name%22%2C%22id%22%3A%2242%22%2C%22meta%22%3A%7B%22foo%22%3Atrue%7D%2C%22description%22%3A%22child-test-descripton%22%7D%7D",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -58,13 +64,16 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: '1',
|
||||
},
|
||||
description: 'long long test-descripton,'.repeat(1000),
|
||||
};
|
||||
|
||||
const value = new ExecutionContextContainer(context).toHeader();
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22description%22%3A%22long%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test",
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22meta%22%3A%7B%22foo%22%3A%221%22%7D%2C%22description%22%3A%22long%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20long%20test-descripton%2Clong%20lo",
|
||||
}
|
||||
`);
|
||||
|
||||
|
@ -78,13 +87,16 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 'meta',
|
||||
},
|
||||
description: 'описание',
|
||||
};
|
||||
|
||||
const value = new ExecutionContextContainer(context).toHeader();
|
||||
expect(value).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22description%22%3A%22%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%22%7D",
|
||||
"x-kbn-context": "%7B%22type%22%3A%22test-type%22%2C%22name%22%3A%22test-name%22%2C%22id%22%3A%2242%22%2C%22meta%22%3A%7B%22foo%22%3A%22meta%22%7D%2C%22description%22%3A%22%D0%BE%D0%BF%D0%B8%D1%81%D0%B0%D0%BD%D0%B8%D0%B5%22%7D",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
@ -95,6 +107,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: false,
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
|
||||
|
@ -107,6 +122,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'child-b-type',
|
||||
name: 'child-b-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'child-b-descripton',
|
||||
};
|
||||
|
||||
|
|
|
@ -32,57 +32,103 @@ describe('ExecutionContextService', () => {
|
|||
const context$ = analytics.registerContextProvider.mock.calls[0][0].context$;
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
await expect(firstValueFrom(context$)).resolves.toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"applicationId": "app1",
|
||||
"entityId": undefined,
|
||||
"page": undefined,
|
||||
"pageName": "ghf:app1",
|
||||
}
|
||||
`);
|
||||
Object {
|
||||
"applicationId": "app1",
|
||||
"entityId": undefined,
|
||||
"page": undefined,
|
||||
"pageName": "ghf:app1",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('app name updates automatically and clears everything else', () => {
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: 1,
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
expect(execContext.get()).toStrictEqual({
|
||||
name: 'app1',
|
||||
description: 'first set',
|
||||
type: 'ghf',
|
||||
url: '/',
|
||||
});
|
||||
expect(execContext.get()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
description: 'first set',
|
||||
type: 'ghf',
|
||||
url: '/',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"description": "first set",
|
||||
"meta": Object {
|
||||
"foo": 1,
|
||||
},
|
||||
"name": "app1",
|
||||
"type": "ghf",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
curApp$.next('app2');
|
||||
|
||||
expect(execContext.get()).toStrictEqual({
|
||||
name: 'app2',
|
||||
url: '/',
|
||||
});
|
||||
expect(execContext.get()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app2',
|
||||
url: '/',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"name": "app2",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('sets context and adds current url and appid when getting it', () => {
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: false,
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
expect(execContext.get()).toStrictEqual({
|
||||
name: 'app1',
|
||||
description: 'first set',
|
||||
type: 'ghf',
|
||||
url: '/',
|
||||
});
|
||||
expect(execContext.get()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
description: 'first set',
|
||||
type: 'ghf',
|
||||
url: '/',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"description": "first set",
|
||||
"meta": Object {
|
||||
"foo": false,
|
||||
},
|
||||
"name": "app1",
|
||||
"type": "ghf",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('merges context between calls and gets it', () => {
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: true,
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
|
@ -91,12 +137,25 @@ describe('ExecutionContextService', () => {
|
|||
description: 'second set',
|
||||
});
|
||||
|
||||
expect(execContext.get()).toStrictEqual({
|
||||
name: 'app1',
|
||||
type: 'ghf',
|
||||
description: 'second set',
|
||||
url: '/',
|
||||
});
|
||||
expect(execContext.get()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
type: 'ghf',
|
||||
description: 'second set',
|
||||
url: '/',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"description": "second set",
|
||||
"meta": Object {
|
||||
"foo": true,
|
||||
},
|
||||
"name": "app1",
|
||||
"type": "ghf",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('context observable fires the context each time it changes', () => {
|
||||
|
@ -104,6 +163,9 @@ describe('ExecutionContextService', () => {
|
|||
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: 'meta',
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
|
@ -113,6 +175,9 @@ describe('ExecutionContextService', () => {
|
|||
name: 'app1',
|
||||
type: 'ghf',
|
||||
description: 'first set',
|
||||
meta: {
|
||||
foo: 'meta',
|
||||
},
|
||||
url: '/',
|
||||
});
|
||||
|
||||
|
@ -124,6 +189,9 @@ describe('ExecutionContextService', () => {
|
|||
expect(sub).toHaveBeenCalledWith({
|
||||
name: 'app1',
|
||||
type: 'str',
|
||||
meta: {
|
||||
foo: 'meta',
|
||||
},
|
||||
description: 'first set',
|
||||
url: '/',
|
||||
});
|
||||
|
@ -136,6 +204,9 @@ describe('ExecutionContextService', () => {
|
|||
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
|
||||
|
@ -148,6 +219,9 @@ describe('ExecutionContextService', () => {
|
|||
expect(sub).toHaveBeenCalledWith({
|
||||
name: 'app1',
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'first set',
|
||||
url: '/',
|
||||
});
|
||||
|
@ -160,6 +234,9 @@ describe('ExecutionContextService', () => {
|
|||
|
||||
execContext.set({
|
||||
type: 'ghf',
|
||||
meta: {
|
||||
foo: true,
|
||||
},
|
||||
description: 'first set',
|
||||
});
|
||||
execContext.context$.subscribe(sub);
|
||||
|
@ -180,16 +257,28 @@ describe('ExecutionContextService', () => {
|
|||
description: 'first set',
|
||||
page: 'mypage',
|
||||
child: {
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'inner',
|
||||
},
|
||||
id: '123',
|
||||
});
|
||||
|
||||
expect(execContext.getAsLabels()).toStrictEqual({
|
||||
name: 'app1',
|
||||
page: 'mypage',
|
||||
id: '123',
|
||||
});
|
||||
expect(execContext.getAsLabels()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
page: 'mypage',
|
||||
id: '123',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"id": "123",
|
||||
"name": "app1",
|
||||
"page": "mypage",
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('getAsLabels removes undefined values', () => {
|
||||
|
@ -197,22 +286,48 @@ describe('ExecutionContextService', () => {
|
|||
type: 'ghf',
|
||||
description: 'first set',
|
||||
page: 'mypage',
|
||||
meta: {
|
||||
foo: false,
|
||||
},
|
||||
id: undefined,
|
||||
});
|
||||
|
||||
expect(execContext.get()).toStrictEqual({
|
||||
name: 'app1',
|
||||
type: 'ghf',
|
||||
page: 'mypage',
|
||||
url: '/',
|
||||
description: 'first set',
|
||||
id: undefined,
|
||||
});
|
||||
expect(execContext.get()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
type: 'ghf',
|
||||
page: 'mypage',
|
||||
url: '/',
|
||||
description: 'first set',
|
||||
id: undefined,
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"description": "first set",
|
||||
"id": undefined,
|
||||
"meta": Object {
|
||||
"foo": false,
|
||||
},
|
||||
"name": "app1",
|
||||
"page": "mypage",
|
||||
"type": "ghf",
|
||||
"url": "/",
|
||||
}
|
||||
`
|
||||
);
|
||||
|
||||
expect(execContext.getAsLabels()).toStrictEqual({
|
||||
name: 'app1',
|
||||
page: 'mypage',
|
||||
});
|
||||
expect(execContext.getAsLabels()).toMatchInlineSnapshot(
|
||||
{
|
||||
name: 'app1',
|
||||
page: 'mypage',
|
||||
},
|
||||
`
|
||||
Object {
|
||||
"name": "app1",
|
||||
"page": "mypage",
|
||||
}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('stop clears subscriptions', () => {
|
||||
|
|
|
@ -27,6 +27,8 @@ export type KibanaExecutionContext = {
|
|||
readonly description?: string;
|
||||
/** in browser - url to navigate to a current page, on server - endpoint path, for task: task SO url */
|
||||
readonly url?: string;
|
||||
/** Metadata attached to the field. An optional parameter that allows to describe the execution context in more detail. **/
|
||||
readonly meta?: { [key: string]: string | number | boolean | undefined };
|
||||
/** an inner context spawned from the current context. */
|
||||
child?: KibanaExecutionContext;
|
||||
};
|
||||
|
|
|
@ -65,6 +65,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: true,
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
|
||||
|
@ -84,6 +87,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'child-test-type',
|
||||
name: 'child-test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
|
||||
|
@ -98,6 +104,9 @@ describe('KibanaExecutionContext', () => {
|
|||
id: 'Visualization☺漢字',
|
||||
type: 'test☺type',
|
||||
name: 'test漢name',
|
||||
meta: {
|
||||
foo: 'test漢name',
|
||||
},
|
||||
description: 'test字description',
|
||||
};
|
||||
|
||||
|
@ -112,6 +121,9 @@ describe('KibanaExecutionContext', () => {
|
|||
id: 'Dashboard☺漢字',
|
||||
type: 'test☺type',
|
||||
name: 'test漢name',
|
||||
meta: {
|
||||
foo: 'test漢name',
|
||||
},
|
||||
description: 'parent-descripton',
|
||||
};
|
||||
const parentContainer = new ExecutionContextContainer(parentContext);
|
||||
|
@ -135,6 +147,9 @@ describe('KibanaExecutionContext', () => {
|
|||
new ExecutionContextContainer({
|
||||
type: 'test-type'.repeat(1000),
|
||||
name: 'test-name',
|
||||
meta: {
|
||||
foo: 'test-meta',
|
||||
},
|
||||
id: '42'.repeat(1000),
|
||||
description: 'test-descripton',
|
||||
}).toString(),
|
||||
|
@ -149,6 +164,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'test-type',
|
||||
name: 'test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 'test',
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
|
||||
|
@ -161,6 +179,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'type',
|
||||
name: 'name',
|
||||
id: '41',
|
||||
meta: {
|
||||
foo: true,
|
||||
},
|
||||
description: 'descripton',
|
||||
};
|
||||
|
||||
|
@ -168,6 +189,9 @@ describe('KibanaExecutionContext', () => {
|
|||
type: 'child-test-type',
|
||||
name: 'child-test-name',
|
||||
id: '42',
|
||||
meta: {
|
||||
foo: 42,
|
||||
},
|
||||
description: 'test-descripton',
|
||||
};
|
||||
const contextContainer = new ExecutionContextContainer(context);
|
||||
|
|
|
@ -129,6 +129,6 @@ pageLoadAssetSize:
|
|||
eventAnnotation: 19334
|
||||
screenshotting: 22870
|
||||
synthetics: 40958
|
||||
expressionXY: 34000
|
||||
expressionXY: 36000
|
||||
kibanaUsageCollection: 16463
|
||||
kubernetesSecurity: 77234
|
||||
|
|
|
@ -23,7 +23,7 @@ export const storybookAliases = {
|
|||
es_ui_shared: 'src/plugins/es_ui_shared/.storybook',
|
||||
expression_error: 'src/plugins/expression_error/.storybook',
|
||||
expression_image: 'src/plugins/expression_image/.storybook',
|
||||
expression_metric_vis: 'src/plugins/chart_expressions/expression_metric/.storybook',
|
||||
expression_metric_vis: 'src/plugins/chart_expressions/expression_legacy_metric/.storybook',
|
||||
expression_metric: 'src/plugins/expression_metric/.storybook',
|
||||
expression_partition_vis: 'src/plugins/chart_expressions/expression_partition_vis/.storybook',
|
||||
expression_repeat_image: 'src/plugins/expression_repeat_image/.storybook',
|
||||
|
|
9
src/plugins/chart_expressions/common/index.ts
Normal file
9
src/plugins/chart_expressions/common/index.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 { extractContainerType, extractVisualizationType } from './utils';
|
35
src/plugins/chart_expressions/common/utils.ts
Normal file
35
src/plugins/chart_expressions/common/utils.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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 { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
|
||||
export const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const extractVisualizationType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
} else {
|
||||
return item;
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
|
@ -16,6 +16,7 @@ import {
|
|||
GaugeLabelMajorModes,
|
||||
GaugeTicksPositions,
|
||||
} from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#gauge', () => {
|
||||
const fn = functionWrapper(gaugeFunction());
|
||||
|
@ -39,7 +40,7 @@ describe('interpreter/functions#gauge', () => {
|
|||
const checkArg = (arg: keyof GaugeArguments, options: Record<string, string>) => {
|
||||
Object.values(options).forEach((option) => {
|
||||
it(`returns an object with the correct structure for the ${option} ${arg}`, () => {
|
||||
const actual = fn(context, { ...args, [arg]: option }, undefined);
|
||||
const actual = fn(context, { ...args, [arg]: option });
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
});
|
||||
|
@ -51,55 +52,43 @@ describe('interpreter/functions#gauge', () => {
|
|||
checkArg('labelMajorMode', GaugeLabelMajorModes);
|
||||
|
||||
it(`returns an object with the correct structure for the circle if centralMajor and centralMajorMode are passed`, () => {
|
||||
const actual = fn(
|
||||
context,
|
||||
{
|
||||
...args,
|
||||
shape: GaugeShapes.CIRCLE,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
},
|
||||
undefined
|
||||
);
|
||||
const actual = fn(context, {
|
||||
...args,
|
||||
shape: GaugeShapes.CIRCLE,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
});
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it(`returns an object with the correct structure for the arc if centralMajor and centralMajorMode are passed`, () => {
|
||||
const actual = fn(
|
||||
context,
|
||||
{
|
||||
...args,
|
||||
shape: GaugeShapes.ARC,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
},
|
||||
undefined
|
||||
);
|
||||
const actual = fn(context, {
|
||||
...args,
|
||||
shape: GaugeShapes.ARC,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
});
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it(`throws error if centralMajor or centralMajorMode are provided for the horizontalBullet shape`, () => {
|
||||
const actual = () =>
|
||||
fn(
|
||||
context,
|
||||
{ ...args, centralMajor: 'Some label', centralMajorMode: GaugeCentralMajorModes.CUSTOM },
|
||||
undefined
|
||||
);
|
||||
fn(context, {
|
||||
...args,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
});
|
||||
expect(actual).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it(`throws error if centralMajor or centralMajorMode are provided for the vertical shape`, () => {
|
||||
const actual = () =>
|
||||
fn(
|
||||
context,
|
||||
{
|
||||
...args,
|
||||
shape: GaugeShapes.VERTICAL_BULLET,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
},
|
||||
undefined
|
||||
);
|
||||
fn(context, {
|
||||
...args,
|
||||
shape: GaugeShapes.VERTICAL_BULLET,
|
||||
centralMajor: 'Some label',
|
||||
centralMajorMode: GaugeCentralMajorModes.CUSTOM,
|
||||
});
|
||||
expect(actual).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
|
@ -114,8 +103,10 @@ describe('interpreter/functions#gauge', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, args, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, args, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -24,7 +24,6 @@ import {
|
|||
GaugeColorModes,
|
||||
GaugeCentralMajorModes,
|
||||
} from '../constants';
|
||||
|
||||
export type GaugeColorMode = $Values<typeof GaugeColorModes>;
|
||||
export type GaugeShape = $Values<typeof GaugeShapes>;
|
||||
export type GaugeLabelMajorMode = $Values<typeof GaugeLabelMajorModes>;
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["expressions", "fieldFormats", "charts", "visualizations", "presentationUtil", "data"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": [],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"extraPublicDirs": ["common"]
|
||||
}
|
||||
|
|
|
@ -9,39 +9,71 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { EXPRESSION_GAUGE_NAME, GaugeExpressionProps } from '../../common';
|
||||
import { getFormatService, getPaletteService, getThemeService } from '../services';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpressionGaugePluginStart } from '../plugin';
|
||||
import { EXPRESSION_GAUGE_NAME, GaugeExpressionProps, GaugeShapes } from '../../common';
|
||||
import { getFormatService, getPaletteService } from '../services';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
interface ExpressionGaugeRendererDependencies {
|
||||
theme: ThemeServiceStart;
|
||||
getStartDeps: StartServicesGetter<ExpressionGaugePluginStart>;
|
||||
}
|
||||
|
||||
export const gaugeRenderer: (
|
||||
deps: ExpressionGaugeRendererDependencies
|
||||
) => ExpressionRenderDefinition<GaugeExpressionProps> = ({ theme }) => ({
|
||||
) => ExpressionRenderDefinition<GaugeExpressionProps> = ({ getStartDeps }) => ({
|
||||
name: EXPRESSION_GAUGE_NAME,
|
||||
displayName: i18n.translate('expressionGauge.renderer.visualizationName', {
|
||||
defaultMessage: 'Gauge',
|
||||
}),
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, config, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
const renderComplete = () => {
|
||||
let type: string;
|
||||
|
||||
switch (config.args.shape) {
|
||||
case GaugeShapes.HORIZONTAL_BULLET:
|
||||
type = `${EXPRESSION_GAUGE_NAME}_horizontal`;
|
||||
break;
|
||||
case GaugeShapes.VERTICAL_BULLET:
|
||||
type = `${EXPRESSION_GAUGE_NAME}_vertical`;
|
||||
break;
|
||||
default:
|
||||
type = EXPRESSION_GAUGE_NAME;
|
||||
}
|
||||
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_${type}`,
|
||||
]);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
const { GaugeComponent } = await import('../components/gauge_component');
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<div className="gauge-container" data-test-subj="gaugeChart">
|
||||
<GaugeComponent
|
||||
{...config}
|
||||
formatFactory={getFormatService().deserialize}
|
||||
chartsThemeService={getThemeService()}
|
||||
chartsThemeService={plugins.charts.theme}
|
||||
paletteService={getPaletteService()}
|
||||
renderComplete={() => handlers.done()}
|
||||
renderComplete={renderComplete}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { gaugeFunction } from '../common';
|
||||
import { setFormatService, setThemeService, setPaletteService } from './services';
|
||||
import { setFormatService, setPaletteService } from './services';
|
||||
import { gaugeRenderer } from './expression_renderers';
|
||||
|
||||
/** @internal */
|
||||
|
@ -22,18 +24,25 @@ export interface ExpressionGaugePluginSetup {
|
|||
/** @internal */
|
||||
export interface ExpressionGaugePluginStart {
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
charts: ChartsPluginStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class ExpressionGaugePlugin {
|
||||
public setup(core: CoreSetup, { expressions, charts }: ExpressionGaugePluginSetup) {
|
||||
setThemeService(charts.theme);
|
||||
public setup(
|
||||
core: CoreSetup<ExpressionGaugePluginStart, void>,
|
||||
{ expressions, charts }: ExpressionGaugePluginSetup
|
||||
) {
|
||||
charts.palettes.getPalettes().then((palettes) => {
|
||||
setPaletteService(palettes);
|
||||
});
|
||||
const getStartDeps = createStartServicesGetter<ExpressionGaugePluginStart, void>(
|
||||
core.getStartServices
|
||||
);
|
||||
|
||||
expressions.registerFunction(gaugeFunction);
|
||||
expressions.registerRenderer(gaugeRenderer({ theme: core.theme }));
|
||||
expressions.registerRenderer(gaugeRenderer({ getStartDeps }));
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { fieldFormats }: ExpressionGaugePluginStart) {
|
||||
|
|
|
@ -7,5 +7,4 @@
|
|||
*/
|
||||
|
||||
export { getFormatService, setFormatService } from './format_service';
|
||||
export { getThemeService, setThemeService } from './theme_service';
|
||||
export { getPaletteService, setPaletteService } from './palette_service';
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { HeatmapArguments } from '..';
|
|||
import { functionWrapper } from '@kbn/expressions-plugin/common/expression_functions/specs/tests/utils';
|
||||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { EXPRESSION_HEATMAP_GRID_NAME, EXPRESSION_HEATMAP_LEGEND_NAME } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#heatmap', () => {
|
||||
const fn = functionWrapper(heatmapFunction());
|
||||
|
@ -56,7 +57,7 @@ describe('interpreter/functions#heatmap', () => {
|
|||
};
|
||||
|
||||
it('returns an object with the correct structure', () => {
|
||||
const actual = fn(context, args, undefined);
|
||||
const actual = fn(context, args);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
@ -72,8 +73,10 @@ describe('interpreter/functions#heatmap', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, args, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, args, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -11,6 +11,6 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["expressions", "fieldFormats", "charts", "visualizations", "presentationUtil", "data"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": [],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"extraPublicDirs": ["common"]
|
||||
}
|
||||
|
|
|
@ -9,9 +9,11 @@ import { i18n } from '@kbn/i18n';
|
|||
import React from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import type { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpressionHeatmapPluginStart } from '../plugin';
|
||||
import {
|
||||
EXPRESSION_HEATMAP_NAME,
|
||||
HeatmapExpressionProps,
|
||||
|
@ -23,23 +25,25 @@ import {
|
|||
getFormatService,
|
||||
getPaletteService,
|
||||
getUISettings,
|
||||
getThemeService,
|
||||
} from '../services';
|
||||
import { getTimeZone } from '../utils/get_timezone';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
interface ExpressioHeatmapRendererDependencies {
|
||||
theme: ThemeServiceStart;
|
||||
getStartDeps: StartServicesGetter<ExpressionHeatmapPluginStart>;
|
||||
}
|
||||
|
||||
export const heatmapRenderer: (
|
||||
deps: ExpressioHeatmapRendererDependencies
|
||||
) => ExpressionRenderDefinition<HeatmapExpressionProps> = ({ theme }) => ({
|
||||
) => ExpressionRenderDefinition<HeatmapExpressionProps> = ({ getStartDeps }) => ({
|
||||
name: EXPRESSION_HEATMAP_NAME,
|
||||
displayName: i18n.translate('expressionHeatmap.visualizationName', {
|
||||
defaultMessage: 'Heatmap',
|
||||
}),
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, config, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
@ -50,11 +54,26 @@ export const heatmapRenderer: (
|
|||
handlers.event({ name: 'brush', data });
|
||||
};
|
||||
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_${EXPRESSION_HEATMAP_NAME}`,
|
||||
]);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
const timeZone = getTimeZone(getUISettings());
|
||||
const { HeatmapComponent } = await import('../components/heatmap_component');
|
||||
const { isInteractive } = handlers;
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<div className="heatmap-container" data-test-subj="heatmapChart">
|
||||
<HeatmapComponent
|
||||
{...config}
|
||||
|
@ -63,9 +82,9 @@ export const heatmapRenderer: (
|
|||
timeZone={timeZone}
|
||||
datatableUtilities={getDatatableUtilities()}
|
||||
formatFactory={getFormatService().deserialize}
|
||||
chartsThemeService={getThemeService()}
|
||||
chartsThemeService={plugins.charts.theme}
|
||||
paletteService={getPaletteService()}
|
||||
renderComplete={() => handlers.done()}
|
||||
renderComplete={renderComplete}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
interactive={isInteractive()}
|
||||
/>
|
||||
|
|
|
@ -5,18 +5,19 @@
|
|||
* in compliance with, at your election, the Elastic License 2.0 or the Server
|
||||
* Side Public License, v 1.
|
||||
*/
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { heatmapFunction, heatmapLegendConfig, heatmapGridConfig } from '../common';
|
||||
import {
|
||||
setDatatableUtilities,
|
||||
setFormatService,
|
||||
setPaletteService,
|
||||
setUISettings,
|
||||
setThemeService,
|
||||
} from './services';
|
||||
import { heatmapRenderer } from './expression_renderers';
|
||||
|
||||
|
@ -30,20 +31,29 @@ export interface ExpressionHeatmapPluginSetup {
|
|||
export interface ExpressionHeatmapPluginStart {
|
||||
data: DataPublicPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
charts: ChartsPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class ExpressionHeatmapPlugin {
|
||||
public setup(core: CoreSetup, { expressions, charts }: ExpressionHeatmapPluginSetup) {
|
||||
public setup(
|
||||
core: CoreSetup<ExpressionHeatmapPluginStart, void>,
|
||||
{ expressions, charts }: ExpressionHeatmapPluginSetup
|
||||
) {
|
||||
charts.palettes.getPalettes().then((palettes) => {
|
||||
setPaletteService(palettes);
|
||||
});
|
||||
setUISettings(core.uiSettings);
|
||||
setThemeService(charts.theme);
|
||||
|
||||
const getStartDeps = createStartServicesGetter<ExpressionHeatmapPluginStart, void>(
|
||||
core.getStartServices
|
||||
);
|
||||
|
||||
expressions.registerFunction(heatmapFunction);
|
||||
expressions.registerFunction(heatmapLegendConfig);
|
||||
expressions.registerFunction(heatmapGridConfig);
|
||||
expressions.registerRenderer(heatmapRenderer({ theme: core.theme }));
|
||||
expressions.registerRenderer(heatmapRenderer({ getStartDeps }));
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { data, fieldFormats }: ExpressionHeatmapPluginStart) {
|
||||
|
|
|
@ -8,10 +8,5 @@
|
|||
|
||||
export { getDatatableUtilities, setDatatableUtilities } from './datatable_utilities';
|
||||
export { getFormatService, setFormatService } from './format_service';
|
||||
export {
|
||||
getPaletteService,
|
||||
setPaletteService,
|
||||
setThemeService,
|
||||
getThemeService,
|
||||
} from './palette_service';
|
||||
export { getPaletteService, setPaletteService } from './palette_service';
|
||||
export { getUISettings, setUISettings } from './ui_settings';
|
||||
|
|
|
@ -8,10 +8,6 @@
|
|||
|
||||
import type { PaletteRegistry } from '@kbn/coloring';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
|
||||
export const [getPaletteService, setPaletteService] =
|
||||
createGetterSetter<PaletteRegistry>('palette');
|
||||
|
||||
export const [getThemeService, setThemeService] =
|
||||
createGetterSetter<ChartsPluginSetup['theme']>('charts.theme');
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
|
|
|
@ -11,6 +11,7 @@ import type { MetricArguments } from '..';
|
|||
import { functionWrapper } from '@kbn/expressions-plugin/common/expression_functions/specs/tests/utils';
|
||||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { LabelPosition } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#metric', () => {
|
||||
const fn = functionWrapper(metricVisFunction());
|
||||
|
@ -55,7 +56,7 @@ describe('interpreter/functions#metric', () => {
|
|||
});
|
||||
|
||||
it('returns an object with the correct structure', () => {
|
||||
const actual = fn(context, args, undefined);
|
||||
const actual = fn(context, args);
|
||||
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
@ -71,8 +72,10 @@ describe('interpreter/functions#metric', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, args, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, args, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
@ -88,7 +91,7 @@ describe('interpreter/functions#metric', () => {
|
|||
},
|
||||
};
|
||||
|
||||
expect(() => fn(context, args, undefined)).toThrowErrorMatchingSnapshot();
|
||||
expect(() => fn(context, args)).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it('returns error if several metrics and colorFullBackground specified', () => {
|
||||
|
@ -102,13 +105,13 @@ describe('interpreter/functions#metric', () => {
|
|||
},
|
||||
});
|
||||
|
||||
expect(() => fn(context, args, undefined)).toThrowErrorMatchingSnapshot();
|
||||
expect(() => fn(context, args)).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
|
||||
it('returns error if data includes several rows and colorFullBackground specified', () => {
|
||||
args.colorFullBackground = true;
|
||||
context.rows.push({ 'col-0-1': 0 });
|
||||
|
||||
expect(() => fn(context, args, undefined)).toThrowErrorMatchingSnapshot();
|
||||
expect(() => fn(context, args)).toThrowErrorMatchingSnapshot();
|
||||
});
|
||||
});
|
||||
|
|
|
@ -17,5 +17,5 @@
|
|||
"presentationUtil"
|
||||
],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": ["usageCollection"]
|
||||
}
|
||||
|
|
|
@ -6,8 +6,11 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
export const getFormatService = () => ({
|
||||
deserialize: (target: any) => ({
|
||||
convert: (text: string, format: string) => text,
|
||||
}),
|
||||
});
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
|
||||
export const getFormatService = () =>
|
||||
({
|
||||
deserialize: (target: any) => ({
|
||||
convert: (text: string, format: string) => text,
|
||||
}),
|
||||
} as FieldFormatsStart);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
*/
|
||||
|
||||
import { CustomPaletteState } from '@kbn/charts-plugin/common';
|
||||
import type { PaletteRegistry } from '@kbn/coloring';
|
||||
|
||||
export const getPaletteService = () => {
|
||||
return {
|
||||
|
@ -17,5 +18,5 @@ export const getPaletteService = () => {
|
|||
return colors[lessThenValueIndex];
|
||||
},
|
||||
}),
|
||||
};
|
||||
} as unknown as PaletteRegistry;
|
||||
};
|
||||
|
|
|
@ -13,9 +13,14 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
|||
import { Datatable, DatatableColumn } from '@kbn/expressions-plugin';
|
||||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { ColorMode, CustomPaletteState } from '@kbn/charts-plugin/common';
|
||||
import { getFormatService } from '../__mocks__/format_service';
|
||||
import { getPaletteService } from '../__mocks__/palette_service';
|
||||
import { ExpressionMetricVisRendererDependencies } from '../expression_renderers/metric_vis_renderer';
|
||||
import { getMetricVisRenderer } from '../expression_renderers';
|
||||
import { MetricStyle, MetricVisRenderConfig, visType } from '../../common/types';
|
||||
import { LabelPosition } from '../../common/constants';
|
||||
import { setFormatService } from '../services/format_service';
|
||||
import { setPaletteService } from '../services/palette_service';
|
||||
|
||||
const palette: CustomPaletteState = {
|
||||
colors: ['rgb(219 231 38)', 'rgb(112 38 231)', 'rgb(38 124 231)'],
|
||||
|
@ -124,7 +129,21 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const metricVisRenderer = getMetricVisRenderer({ theme$: from([{ darkMode: false }]) });
|
||||
setFormatService(getFormatService());
|
||||
setPaletteService(getPaletteService());
|
||||
|
||||
const getStartDeps = (() => ({
|
||||
core: {
|
||||
theme: {
|
||||
theme$: from([{ darkMode: false }]),
|
||||
},
|
||||
},
|
||||
})) as unknown as ExpressionMetricVisRendererDependencies['getStartDeps'];
|
||||
|
||||
const metricVisRenderer = () =>
|
||||
getMetricVisRenderer({
|
||||
getStartDeps,
|
||||
});
|
||||
|
||||
storiesOf('renderers/visMetric', module)
|
||||
.add('Default', () => {
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
|
||||
import React, { lazy } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import {
|
||||
ExpressionValueVisDimension,
|
||||
|
@ -21,7 +20,10 @@ import {
|
|||
} from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { getColumnByAccessor } from '@kbn/visualizations-plugin/common/utils';
|
||||
import { Datatable } from '@kbn/expressions-plugin';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { ExpressionLegacyMetricPluginStart } from '../plugin';
|
||||
import { EXPRESSION_METRIC_NAME, MetricVisRenderConfig, VisParams } from '../../common';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
// @ts-ignore
|
||||
const MetricVisComponent = lazy(() => import('../components/metric_component'));
|
||||
|
@ -53,39 +55,59 @@ async function metricFilterable(
|
|||
);
|
||||
}
|
||||
|
||||
export const getMetricVisRenderer = (
|
||||
theme: ThemeServiceStart
|
||||
): (() => ExpressionRenderDefinition<MetricVisRenderConfig>) => {
|
||||
return () => ({
|
||||
name: EXPRESSION_METRIC_NAME,
|
||||
displayName: 'metric visualization',
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visData, visConfig }, handlers) => {
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
/** @internal **/
|
||||
export interface ExpressionMetricVisRendererDependencies {
|
||||
getStartDeps: StartServicesGetter<ExpressionLegacyMetricPluginStart>;
|
||||
}
|
||||
|
||||
const filterable = await metricFilterable(visConfig.dimensions, visData, handlers);
|
||||
export const getMetricVisRenderer: (
|
||||
deps: ExpressionMetricVisRendererDependencies
|
||||
) => ExpressionRenderDefinition<MetricVisRenderConfig> = ({ getStartDeps }) => ({
|
||||
name: EXPRESSION_METRIC_NAME,
|
||||
displayName: 'metric visualization',
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visData, visConfig }, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<VisualizationContainer
|
||||
data-test-subj="legacyMtrVis"
|
||||
className="legacyMtrVis"
|
||||
showNoResult={!visData.rows?.length}
|
||||
handlers={handlers}
|
||||
>
|
||||
<MetricVisComponent
|
||||
visData={visData}
|
||||
visParams={visConfig}
|
||||
renderComplete={() => handlers.done()}
|
||||
fireEvent={handlers.event}
|
||||
filterable={filterable}
|
||||
/>
|
||||
</VisualizationContainer>
|
||||
</KibanaThemeProvider>,
|
||||
domNode
|
||||
);
|
||||
},
|
||||
});
|
||||
};
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
const filterable = await metricFilterable(visConfig.dimensions, visData, handlers);
|
||||
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_legacy_metric`,
|
||||
]);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<VisualizationContainer
|
||||
data-test-subj="legacyMtrVis"
|
||||
className="legacyMtrVis"
|
||||
showNoResult={!visData.rows?.length}
|
||||
renderComplete={renderComplete}
|
||||
handlers={handlers}
|
||||
>
|
||||
<MetricVisComponent
|
||||
visData={visData}
|
||||
visParams={visConfig}
|
||||
renderComplete={renderComplete}
|
||||
fireEvent={handlers.event}
|
||||
filterable={filterable}
|
||||
/>
|
||||
</VisualizationContainer>
|
||||
</KibanaThemeProvider>,
|
||||
domNode
|
||||
);
|
||||
},
|
||||
});
|
||||
|
|
|
@ -10,6 +10,8 @@ import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
|||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { metricVisFunction } from '../common';
|
||||
import { setFormatService, setPaletteService } from './services';
|
||||
import { getMetricVisRenderer } from './expression_renderers';
|
||||
|
@ -23,16 +25,25 @@ export interface ExpressionLegacyMetricPluginSetup {
|
|||
/** @internal */
|
||||
export interface ExpressionLegacyMetricPluginStart {
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class ExpressionLegacyMetricPlugin implements Plugin<void, void> {
|
||||
public setup(core: CoreSetup, { expressions, charts }: ExpressionLegacyMetricPluginSetup) {
|
||||
expressions.registerFunction(metricVisFunction);
|
||||
expressions.registerRenderer(getMetricVisRenderer(core.theme));
|
||||
export class ExpressionLegacyMetricPlugin implements Plugin {
|
||||
public setup(
|
||||
core: CoreSetup<ExpressionLegacyMetricPluginStart, void>,
|
||||
{ expressions, charts }: ExpressionLegacyMetricPluginSetup
|
||||
) {
|
||||
const getStartDeps = createStartServicesGetter<ExpressionLegacyMetricPluginStart, void>(
|
||||
core.getStartServices
|
||||
);
|
||||
|
||||
charts.palettes.getPalettes().then((palettes) => {
|
||||
setPaletteService(palettes);
|
||||
});
|
||||
|
||||
expressions.registerFunction(metricVisFunction);
|
||||
expressions.registerRenderer(getMetricVisRenderer({ getStartDeps }));
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { fieldFormats }: ExpressionLegacyMetricPluginStart) {
|
||||
|
|
|
@ -13,11 +13,13 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../visualizations/tsconfig.json" },
|
||||
]
|
||||
}
|
||||
|
|
|
@ -17,5 +17,5 @@
|
|||
"presentationUtil"
|
||||
],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": ["usageCollection"]
|
||||
}
|
||||
|
|
|
@ -9,29 +9,52 @@
|
|||
import React, { lazy } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import { css } from '@emotion/react';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpressionMetricPluginStart } from '../plugin';
|
||||
import { EXPRESSION_METRIC_NAME, MetricVisRenderConfig } from '../../common';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
const MetricVis = lazy(() => import('../components/metric_vis'));
|
||||
|
||||
interface ExpressionMetricVisRendererDependencies {
|
||||
getStartDeps: StartServicesGetter<ExpressionMetricPluginStart>;
|
||||
}
|
||||
|
||||
export const getMetricVisRenderer = (
|
||||
theme: ThemeServiceStart
|
||||
deps: ExpressionMetricVisRendererDependencies
|
||||
): (() => ExpressionRenderDefinition<MetricVisRenderConfig>) => {
|
||||
return () => ({
|
||||
name: EXPRESSION_METRIC_NAME,
|
||||
displayName: 'metric visualization',
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visData, visConfig }, handlers) => {
|
||||
const { core, plugins } = deps.getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_metric`,
|
||||
]);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<VisualizationContainer
|
||||
data-test-subj="mtrVis"
|
||||
css={css`
|
||||
|
@ -39,9 +62,10 @@ export const getMetricVisRenderer = (
|
|||
width: 100%;
|
||||
`}
|
||||
showNoResult={!visData.rows.length}
|
||||
renderComplete={renderComplete}
|
||||
handlers={handlers}
|
||||
>
|
||||
<MetricVis data={visData} config={visConfig} renderComplete={() => handlers.done()} />
|
||||
<MetricVis data={visData} config={visConfig} renderComplete={renderComplete} />
|
||||
</VisualizationContainer>
|
||||
</KibanaThemeProvider>,
|
||||
domNode
|
||||
|
|
|
@ -10,6 +10,8 @@ import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
|||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { metricVisFunction } from '../common';
|
||||
import { setFormatService, setPaletteService } from './services';
|
||||
import { getMetricVisRenderer } from './expression_renderers';
|
||||
|
@ -25,18 +27,28 @@ export interface ExpressionMetricPluginSetup {
|
|||
/** @internal */
|
||||
export interface ExpressionMetricPluginStart {
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
export class ExpressionMetricPlugin implements Plugin<void, void> {
|
||||
public async setup(core: CoreSetup, { expressions, charts }: ExpressionMetricPluginSetup) {
|
||||
export class ExpressionMetricPlugin implements Plugin {
|
||||
public setup(
|
||||
core: CoreSetup<ExpressionMetricPluginStart, void>,
|
||||
{ expressions, charts }: ExpressionMetricPluginSetup
|
||||
) {
|
||||
const getStartDeps = createStartServicesGetter<ExpressionMetricPluginStart, void>(
|
||||
core.getStartServices
|
||||
);
|
||||
|
||||
charts.palettes.getPalettes().then((palettes) => {
|
||||
setPaletteService(palettes);
|
||||
});
|
||||
|
||||
expressions.registerFunction(metricVisFunction);
|
||||
expressions.registerRenderer(getMetricVisRenderer(core.theme));
|
||||
expressions.registerRenderer(getMetricVisRenderer({ getStartDeps }));
|
||||
|
||||
setUiSettingsService(core.uiSettings);
|
||||
setThemeService(charts.theme);
|
||||
const palettes = await charts.palettes.getPalettes();
|
||||
setPaletteService(palettes);
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { fieldFormats }: ExpressionMetricPluginStart) {
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
|
|
|
@ -17,6 +17,7 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
|||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { mosaicVisFunction } from './mosaic_vis_function';
|
||||
import { PARTITION_LABELS_VALUE } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#mosaicVis', () => {
|
||||
const fn = functionWrapper(mosaicVisFunction());
|
||||
|
@ -138,8 +139,10 @@ describe('interpreter/functions#mosaicVis', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, visConfig, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, visConfig, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -18,6 +18,7 @@ import { ExpressionValueVisDimension, LegendSize } from '@kbn/visualizations-plu
|
|||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { pieVisFunction } from './pie_vis_function';
|
||||
import { PARTITION_LABELS_VALUE } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#pieVis', () => {
|
||||
const fn = functionWrapper(pieVisFunction());
|
||||
|
@ -132,7 +133,9 @@ describe('interpreter/functions#pieVis', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, visConfig, handlers as any);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
|
|
|
@ -17,6 +17,7 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
|||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { treemapVisFunction } from './treemap_vis_function';
|
||||
import { PARTITION_LABELS_VALUE } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#treemapVis', () => {
|
||||
const fn = functionWrapper(treemapVisFunction());
|
||||
|
@ -138,8 +139,10 @@ describe('interpreter/functions#treemapVis', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, visConfig, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, visConfig, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -17,6 +17,7 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
|
|||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { waffleVisFunction } from './waffle_vis_function';
|
||||
import { PARTITION_LABELS_VALUE } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
describe('interpreter/functions#waffleVis', () => {
|
||||
const fn = functionWrapper(waffleVisFunction());
|
||||
|
@ -109,8 +110,10 @@ describe('interpreter/functions#waffleVis', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, visConfig, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, visConfig, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -13,6 +13,6 @@
|
|||
"common"
|
||||
],
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations", "fieldFormats", "presentationUtil"],
|
||||
"requiredBundles": ["kibanaReact"],
|
||||
"optionalPlugins": []
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": ["usageCollection"]
|
||||
}
|
||||
|
|
|
@ -11,10 +11,9 @@ import { action } from '@storybook/addon-actions';
|
|||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { getFormatService } from './format_service';
|
||||
|
||||
const theme = {
|
||||
theme$: from([{ darkMode: false }]),
|
||||
};
|
||||
import { palettes } from './palettes';
|
||||
import { theme } from './theme';
|
||||
import { VisTypePieDependencies } from '../plugin';
|
||||
|
||||
const data = {
|
||||
actions: {
|
||||
|
@ -23,8 +22,20 @@ const data = {
|
|||
},
|
||||
} as DataPublicPluginStart;
|
||||
|
||||
export const getStartDeps = async () => ({
|
||||
export const getStartDeps = (() => ({
|
||||
data,
|
||||
fieldFormats: getFormatService() as FieldFormatsStart,
|
||||
kibanaTheme: theme,
|
||||
});
|
||||
core: {
|
||||
theme: {
|
||||
theme$: from([{ darkMode: false }]),
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
data,
|
||||
fieldFormats: getFormatService() as FieldFormatsStart,
|
||||
charts: {
|
||||
theme,
|
||||
palettes,
|
||||
},
|
||||
},
|
||||
})) as unknown as VisTypePieDependencies['getStartDeps'];
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ComponentStory } from '@storybook/react';
|
|||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { getPartitionVisRenderer } from '../expression_renderers';
|
||||
import { ChartTypes, RenderValue } from '../../common/types';
|
||||
import { palettes, theme, getStartDeps } from '../__mocks__';
|
||||
import { getStartDeps } from '../__mocks__';
|
||||
import { mosaicArgTypes, treemapMosaicConfig, data } from './shared';
|
||||
|
||||
const containerSize = {
|
||||
|
@ -19,7 +19,7 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ palettes, theme, getStartDeps });
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ getStartDeps });
|
||||
|
||||
type Props = {
|
||||
visType: RenderValue['visType'];
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ComponentStory } from '@storybook/react';
|
|||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { getPartitionVisRenderer } from '../expression_renderers';
|
||||
import { ChartTypes, RenderValue } from '../../common/types';
|
||||
import { palettes, theme, getStartDeps } from '../__mocks__';
|
||||
import { getStartDeps } from '../__mocks__';
|
||||
import { pieDonutArgTypes, pieConfig, data } from './shared';
|
||||
|
||||
const containerSize = {
|
||||
|
@ -19,7 +19,7 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ palettes, theme, getStartDeps });
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ getStartDeps });
|
||||
|
||||
type Props = {
|
||||
visType: RenderValue['visType'];
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ComponentStory } from '@storybook/react';
|
|||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { getPartitionVisRenderer } from '../expression_renderers';
|
||||
import { ChartTypes, RenderValue } from '../../common/types';
|
||||
import { palettes, theme, getStartDeps } from '../__mocks__';
|
||||
import { getStartDeps } from '../__mocks__';
|
||||
import { treemapArgTypes, treemapMosaicConfig, data } from './shared';
|
||||
|
||||
const containerSize = {
|
||||
|
@ -19,7 +19,7 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ palettes, theme, getStartDeps });
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ getStartDeps });
|
||||
|
||||
type Props = {
|
||||
visType: RenderValue['visType'];
|
||||
|
|
|
@ -11,7 +11,7 @@ import { ComponentStory } from '@storybook/react';
|
|||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { getPartitionVisRenderer } from '../expression_renderers';
|
||||
import { ChartTypes, RenderValue } from '../../common/types';
|
||||
import { palettes, theme, getStartDeps } from '../__mocks__';
|
||||
import { getStartDeps } from '../__mocks__';
|
||||
import { waffleArgTypes, waffleConfig, data } from './shared';
|
||||
|
||||
const containerSize = {
|
||||
|
@ -19,7 +19,7 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ palettes, theme, getStartDeps });
|
||||
const PartitionVisRenderer = () => getPartitionVisRenderer({ getStartDeps });
|
||||
|
||||
type Props = {
|
||||
visType: RenderValue['visType'];
|
||||
|
|
|
@ -60,7 +60,6 @@ import {
|
|||
} from '../utils';
|
||||
import { ChartSplit, SMALL_MULTIPLES_ID } from './chart_split';
|
||||
import { VisualizationNoResults } from './visualization_noresults';
|
||||
import { VisTypePiePluginStartDependencies } from '../plugin';
|
||||
import {
|
||||
partitionVisWrapperStyle,
|
||||
partitionVisContainerStyle,
|
||||
|
@ -68,7 +67,7 @@ import {
|
|||
} from './partition_vis_component.styles';
|
||||
import { ChartTypes } from '../../common/types';
|
||||
import { filterOutConfig } from '../utils/filter_out_config';
|
||||
import { FilterEvent } from '../types';
|
||||
import { FilterEvent, StartDeps } from '../types';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
|
@ -87,14 +86,13 @@ export interface PartitionVisComponentProps {
|
|||
renderComplete: IInterpreterRenderHandlers['done'];
|
||||
chartsThemeService: ChartsPluginSetup['theme'];
|
||||
palettesRegistry: PaletteRegistry;
|
||||
services: VisTypePiePluginStartDependencies;
|
||||
services: Pick<StartDeps, 'data' | 'fieldFormats'>;
|
||||
syncColors: boolean;
|
||||
}
|
||||
|
||||
const PartitionVisComponent = (props: PartitionVisComponentProps) => {
|
||||
const { visData, visParams: preVisParams, visType, services, syncColors } = props;
|
||||
const visParams = useMemo(() => filterOutConfig(visType, preVisParams), [preVisParams, visType]);
|
||||
|
||||
const chartTheme = props.chartsThemeService.useChartsTheme();
|
||||
const chartBaseTheme = props.chartsThemeService.useChartsBaseTheme();
|
||||
|
||||
|
|
|
@ -15,9 +15,11 @@ import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/public';
|
|||
import type { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import { withSuspense } from '@kbn/presentation-util-plugin/public';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { VisTypePieDependencies } from '../plugin';
|
||||
import { PARTITION_VIS_RENDERER_NAME } from '../../common/constants';
|
||||
import { ChartTypes, RenderValue } from '../../common/types';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
export const strings = {
|
||||
getDisplayName: () =>
|
||||
|
@ -41,33 +43,47 @@ const partitionVisRenderer = css({
|
|||
|
||||
export const getPartitionVisRenderer: (
|
||||
deps: VisTypePieDependencies
|
||||
) => ExpressionRenderDefinition<RenderValue> = ({ theme, palettes, getStartDeps }) => ({
|
||||
) => ExpressionRenderDefinition<RenderValue> = ({ getStartDeps }) => ({
|
||||
name: PARTITION_VIS_RENDERER_NAME,
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visConfig, visData, visType, syncColors }, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
const services = await getStartDeps();
|
||||
const palettesRegistry = await palettes.getPalettes();
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_${visType}`,
|
||||
]);
|
||||
}
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
const palettesRegistry = await plugins.charts.palettes.getPalettes();
|
||||
|
||||
render(
|
||||
<I18nProvider>
|
||||
<KibanaThemeProvider theme$={services.kibanaTheme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<div css={partitionVisRenderer}>
|
||||
<PartitionVisComponent
|
||||
chartsThemeService={theme}
|
||||
chartsThemeService={plugins.charts.theme}
|
||||
palettesRegistry={palettesRegistry}
|
||||
visParams={visConfig}
|
||||
visData={visData}
|
||||
visType={visConfig.isDonut ? ChartTypes.DONUT : visType}
|
||||
renderComplete={() => handlers.done()}
|
||||
renderComplete={renderComplete}
|
||||
fireEvent={handlers.event}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
services={{ data: services.data, fieldFormats: services.fieldFormats }}
|
||||
services={{ data: plugins.data, fieldFormats: plugins.fieldFormats }}
|
||||
syncColors={syncColors}
|
||||
/>
|
||||
</div>
|
||||
|
|
|
@ -6,10 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { CoreSetup, CoreStart, ThemeServiceStart } from '@kbn/core/public';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { CoreSetup, CoreStart } from '@kbn/core/public';
|
||||
import { createStartServicesGetter, StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
partitionLabelsFunction,
|
||||
pieVisFunction,
|
||||
|
@ -27,23 +25,12 @@ import {
|
|||
|
||||
/** @internal */
|
||||
export interface VisTypePieDependencies {
|
||||
theme: ChartsPluginSetup['theme'];
|
||||
palettes: ChartsPluginSetup['palettes'];
|
||||
getStartDeps: () => Promise<{
|
||||
data: DataPublicPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
kibanaTheme: ThemeServiceStart;
|
||||
}>;
|
||||
}
|
||||
|
||||
export interface VisTypePiePluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
getStartDeps: StartServicesGetter<StartDeps>;
|
||||
}
|
||||
|
||||
export class ExpressionPartitionVisPlugin {
|
||||
public setup(
|
||||
core: CoreSetup<VisTypePiePluginStartDependencies>,
|
||||
core: CoreSetup<StartDeps, void>,
|
||||
{ expressions, charts }: SetupDeps
|
||||
): ExpressionPartitionVisPluginSetup {
|
||||
expressions.registerFunction(partitionLabelsFunction);
|
||||
|
@ -52,16 +39,9 @@ export class ExpressionPartitionVisPlugin {
|
|||
expressions.registerFunction(mosaicVisFunction);
|
||||
expressions.registerFunction(waffleVisFunction);
|
||||
|
||||
const getStartDeps = async () => {
|
||||
const [coreStart, deps] = await core.getStartServices();
|
||||
const { data, fieldFormats } = deps;
|
||||
const { theme: kibanaTheme } = coreStart;
|
||||
return { data, fieldFormats, kibanaTheme };
|
||||
};
|
||||
const getStartDeps = createStartServicesGetter<StartDeps, void>(core.getStartServices);
|
||||
|
||||
expressions.registerRenderer(
|
||||
getPartitionVisRenderer({ theme: charts.theme, palettes: charts.palettes, getStartDeps })
|
||||
);
|
||||
expressions.registerRenderer(getPartitionVisRenderer({ getStartDeps }));
|
||||
}
|
||||
|
||||
public start(core: CoreStart, deps: StartDeps): ExpressionPartitionVisPluginStart {}
|
||||
|
|
|
@ -6,11 +6,14 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
import type { ValueClickContext } from '@kbn/embeddable-plugin/public';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import {
|
||||
Plugin as ExpressionsPublicPlugin,
|
||||
ExpressionsServiceStart,
|
||||
} from '@kbn/expressions-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
|
||||
export type ExpressionPartitionVisPluginSetup = void;
|
||||
export type ExpressionPartitionVisPluginStart = void;
|
||||
|
@ -22,6 +25,10 @@ export interface SetupDeps {
|
|||
|
||||
export interface StartDeps {
|
||||
expression: ExpressionsServiceStart;
|
||||
charts: ChartsPluginStart;
|
||||
data: DataPublicPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
export interface FilterEvent {
|
||||
|
|
|
@ -13,8 +13,10 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../data/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
|
|
|
@ -12,6 +12,7 @@ import { functionWrapper } from '@kbn/expressions-plugin/common/expression_funct
|
|||
import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/public';
|
||||
import { Datatable } from '@kbn/expressions-plugin/common/expression_types/specs';
|
||||
import { ScaleOptions, Orientation } from '../constants';
|
||||
import { ExecutionContext } from '@kbn/expressions-plugin';
|
||||
|
||||
type Arguments = Parameters<ReturnType<typeof tagcloudFunction>['fn']>[1];
|
||||
|
||||
|
@ -76,12 +77,12 @@ describe('interpreter/functions#tagcloud', () => {
|
|||
};
|
||||
|
||||
it('returns an object with the correct structure for number accessors', () => {
|
||||
const actual = fn(context, { ...visConfig, ...numberAccessors } as Arguments, undefined);
|
||||
const actual = fn(context, { ...visConfig, ...numberAccessors } as Arguments);
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
it('returns an object with the correct structure for string accessors', () => {
|
||||
const actual = fn(context, { ...visConfig, ...stringAccessors } as Arguments, undefined);
|
||||
const actual = fn(context, { ...visConfig, ...stringAccessors } as Arguments);
|
||||
expect(actual).toMatchSnapshot();
|
||||
});
|
||||
|
||||
|
@ -96,8 +97,10 @@ describe('interpreter/functions#tagcloud', () => {
|
|||
reset: () => {},
|
||||
},
|
||||
},
|
||||
};
|
||||
await fn(context, { ...visConfig, ...numberAccessors } as Arguments, handlers as any);
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext;
|
||||
|
||||
await fn(context, { ...visConfig, ...numberAccessors } as Arguments, handlers);
|
||||
|
||||
expect(loggedTable!).toMatchSnapshot();
|
||||
});
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["expressions", "visualizations", "charts", "presentationUtil", "fieldFormats"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact"],
|
||||
"optionalPlugins": [],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
|
|
|
@ -9,11 +9,12 @@
|
|||
import React from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { Render } from '@kbn/presentation-util-plugin/public/__stories__';
|
||||
import { from } from 'rxjs';
|
||||
import { tagcloudRenderer } from '../expression_renderers';
|
||||
import { TagcloudRendererConfig } from '../../common/types';
|
||||
import { ScaleOptions, Orientation } from '../../common/constants';
|
||||
import { palettes } from '../__mocks__/palettes';
|
||||
import { theme } from '../__mocks__/theme';
|
||||
import { ExpressionTagcloudRendererDependencies } from '../plugin';
|
||||
|
||||
const config: TagcloudRendererConfig = {
|
||||
visType: 'tagcloud',
|
||||
|
@ -65,11 +66,24 @@ const containerSize = {
|
|||
height: '700px',
|
||||
};
|
||||
|
||||
const getStartDeps = (() => ({
|
||||
core: {
|
||||
theme: {
|
||||
theme$: from([{ darkMode: false }]),
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
charts: {
|
||||
palettes,
|
||||
},
|
||||
},
|
||||
})) as ExpressionTagcloudRendererDependencies['getStartDeps'];
|
||||
|
||||
storiesOf('renderers/tag_cloud_vis', module)
|
||||
.add('Default', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={config}
|
||||
{...containerSize}
|
||||
/>
|
||||
|
@ -78,7 +92,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With log scale', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{ ...config, visParams: { ...config.visParams, scale: ScaleOptions.LOG } }}
|
||||
{...containerSize}
|
||||
/>
|
||||
|
@ -87,7 +101,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With square root scale', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{ ...config, visParams: { ...config.visParams, scale: ScaleOptions.SQUARE_ROOT } }}
|
||||
{...containerSize}
|
||||
/>
|
||||
|
@ -96,7 +110,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With right angled orientation', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{
|
||||
...config,
|
||||
visParams: { ...config.visParams, orientation: Orientation.RIGHT_ANGLED },
|
||||
|
@ -108,7 +122,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With multiple orientations', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{
|
||||
...config,
|
||||
visParams: { ...config.visParams, orientation: Orientation.MULTIPLE },
|
||||
|
@ -120,7 +134,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With hidden label', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{ ...config, visParams: { ...config.visParams, showLabel: false } }}
|
||||
{...containerSize}
|
||||
/>
|
||||
|
@ -129,7 +143,7 @@ storiesOf('renderers/tag_cloud_vis', module)
|
|||
.add('With empty results', () => {
|
||||
return (
|
||||
<Render
|
||||
renderer={() => tagcloudRenderer({ palettes, theme })}
|
||||
renderer={() => tagcloudRenderer({ getStartDeps })}
|
||||
config={{ ...config, visData: { ...config.visData, rows: [] } }}
|
||||
{...containerSize}
|
||||
/>
|
||||
|
|
|
@ -14,9 +14,11 @@ import { i18n } from '@kbn/i18n';
|
|||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { ExpressioTagcloudRendererDependencies } from '../plugin';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpressionTagcloudRendererDependencies } from '../plugin';
|
||||
import { TagcloudRendererConfig } from '../../common/types';
|
||||
import { EXPRESSION_NAME } from '../../common';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
export const strings = {
|
||||
getDisplayName: () =>
|
||||
|
@ -36,22 +38,39 @@ const tagCloudVisClass = {
|
|||
const TagCloudChart = lazy(() => import('../components/tagcloud_component'));
|
||||
|
||||
export const tagcloudRenderer: (
|
||||
deps: ExpressioTagcloudRendererDependencies
|
||||
) => ExpressionRenderDefinition<TagcloudRendererConfig> = ({ palettes, theme }) => ({
|
||||
deps: ExpressionTagcloudRendererDependencies
|
||||
) => ExpressionRenderDefinition<TagcloudRendererConfig> = ({ getStartDeps }) => ({
|
||||
name: EXPRESSION_NAME,
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, config, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
const palettesRegistry = await palettes.getPalettes();
|
||||
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (containerType && visualizationType) {
|
||||
plugins.usageCollection?.reportUiCounter(containerType, METRIC_TYPE.COUNT, [
|
||||
`render_${visualizationType}_${EXPRESSION_NAME}`,
|
||||
]);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
const palettesRegistry = await plugins.charts.palettes.getPalettes();
|
||||
|
||||
const showNoResult = config.visData.rows.length === 0;
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<I18nProvider>
|
||||
<ClassNames>
|
||||
{({ css, cx }) => (
|
||||
|
@ -60,12 +79,13 @@ export const tagcloudRenderer: (
|
|||
// Class `tagCloudContainer` is generated by `@emotion/react` and passed as a defined class to `VisualizationContainer`.
|
||||
// It is used for rendering at `Canvas`.
|
||||
className={cx('tagCloudContainer', css(tagCloudVisClass))}
|
||||
renderComplete={renderComplete}
|
||||
showNoResult={showNoResult}
|
||||
>
|
||||
<TagCloudChart
|
||||
{...config}
|
||||
palettesRegistry={palettesRegistry}
|
||||
renderComplete={() => handlers.done()}
|
||||
renderComplete={renderComplete}
|
||||
fireEvent={handlers.event}
|
||||
syncColors={config.syncColors}
|
||||
/>
|
||||
|
|
|
@ -6,10 +6,12 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { CoreSetup, CoreStart, Plugin, ThemeServiceStart } from '@kbn/core/public';
|
||||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { ExpressionsStart, ExpressionsSetup } from '@kbn/expressions-plugin/public';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { createStartServicesGetter, StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { tagcloudRenderer } from './expression_renderers';
|
||||
import { tagcloudFunction } from '../common/expression_functions';
|
||||
import { setFormatService } from './format_service';
|
||||
|
@ -20,14 +22,15 @@ interface SetupDeps {
|
|||
}
|
||||
|
||||
/** @internal */
|
||||
export interface ExpressioTagcloudRendererDependencies {
|
||||
palettes: ChartsPluginSetup['palettes'];
|
||||
theme: ThemeServiceStart;
|
||||
export interface ExpressionTagcloudRendererDependencies {
|
||||
getStartDeps: StartServicesGetter<StartDeps>;
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
expression: ExpressionsStart;
|
||||
charts: ChartsPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
export type ExpressionTagcloudPluginSetup = void;
|
||||
|
@ -37,13 +40,16 @@ export class ExpressionTagcloudPlugin
|
|||
implements
|
||||
Plugin<ExpressionTagcloudPluginSetup, ExpressionTagcloudPluginStart, SetupDeps, StartDeps>
|
||||
{
|
||||
public setup(core: CoreSetup, { expressions, charts }: SetupDeps): ExpressionTagcloudPluginSetup {
|
||||
const rendererDependencies: ExpressioTagcloudRendererDependencies = {
|
||||
palettes: charts.palettes,
|
||||
theme: core.theme,
|
||||
};
|
||||
public setup(
|
||||
core: CoreSetup<StartDeps, ExpressionTagcloudPluginStart>,
|
||||
{ expressions, charts }: SetupDeps
|
||||
): ExpressionTagcloudPluginSetup {
|
||||
const getStartDeps = createStartServicesGetter<StartDeps, ExpressionTagcloudPluginStart>(
|
||||
core.getStartServices
|
||||
);
|
||||
|
||||
expressions.registerFunction(tagcloudFunction);
|
||||
expressions.registerRenderer(tagcloudRenderer(rendererDependencies));
|
||||
expressions.registerRenderer(tagcloudRenderer({ getStartDeps }));
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { fieldFormats }: StartDeps): ExpressionTagcloudPluginStart {
|
||||
|
|
|
@ -13,9 +13,11 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../presentation_util/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../visualizations/tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json" },
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import { LayerTypes } from '../constants';
|
||||
import { DataLayerConfig, CommonXYLayerConfig } from '..';
|
||||
|
||||
export const [getThemeService, setThemeService] =
|
||||
createGetterSetter<ChartsPluginSetup['theme']>('charts.theme');
|
||||
export const isDataLayer = (layer: CommonXYLayerConfig): layer is DataLayerConfig =>
|
||||
layer.layerType === LayerTypes.DATA;
|
|
@ -11,5 +11,5 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["expressions", "charts", "data", "fieldFormats", "uiActions", "eventAnnotation", "visualizations"],
|
||||
"requiredBundles": ["kibanaReact"],
|
||||
"optionalPlugins": []
|
||||
"optionalPlugins": ["usageCollection"]
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@ import { I18nProvider } from '@kbn/i18n-react';
|
|||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import React from 'react';
|
||||
import ReactDOM from 'react-dom';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import type { PaletteRegistry } from '@kbn/coloring';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
|
@ -18,8 +19,12 @@ import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'
|
|||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin';
|
||||
import { FormatFactory } from '@kbn/field-formats-plugin/common';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import type { XYChartProps } from '../../common';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { isDataLayer } from '../../common/utils/layer_types_guards';
|
||||
import { LayerTypes, SeriesTypes } from '../../common/constants';
|
||||
import type { CommonXYLayerConfig, XYChartProps } from '../../common';
|
||||
import type { BrushEvent, FilterEvent } from '../types';
|
||||
import { extractContainerType, extractVisualizationType } from '../../../common';
|
||||
|
||||
export type GetStartDepsFn = () => Promise<{
|
||||
data: DataPublicPluginStart;
|
||||
|
@ -31,12 +36,60 @@ export type GetStartDepsFn = () => Promise<{
|
|||
useLegacyTimeAxis: boolean;
|
||||
kibanaTheme: ThemeServiceStart;
|
||||
eventAnnotationService: EventAnnotationServiceType;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}>;
|
||||
|
||||
interface XyChartRendererDeps {
|
||||
getStartDeps: GetStartDepsFn;
|
||||
}
|
||||
|
||||
const extractCounterEvents = (originatingApp: string, layers: CommonXYLayerConfig[]) => {
|
||||
const dataLayer = layers.find(isDataLayer);
|
||||
if (dataLayer) {
|
||||
const type =
|
||||
dataLayer.seriesType === SeriesTypes.BAR
|
||||
? `${dataLayer.isHorizontal ? 'horizontal_bar' : 'vertical_bar'}`
|
||||
: dataLayer.seriesType;
|
||||
|
||||
const byTypes = layers.reduce(
|
||||
(acc, item) => {
|
||||
if (
|
||||
!acc.mixedXY &&
|
||||
item.layerType === LayerTypes.DATA &&
|
||||
item.seriesType !== dataLayer.seriesType
|
||||
) {
|
||||
acc.mixedXY = true;
|
||||
}
|
||||
|
||||
acc[item.layerType] += 1;
|
||||
return acc;
|
||||
},
|
||||
{
|
||||
mixedXY: false,
|
||||
[LayerTypes.REFERENCELINE]: 0,
|
||||
[LayerTypes.ANNOTATIONS]: 0,
|
||||
[LayerTypes.DATA]: 0,
|
||||
}
|
||||
);
|
||||
|
||||
return [
|
||||
[
|
||||
type,
|
||||
dataLayer.isPercentage ? 'percentage' : undefined,
|
||||
dataLayer.isStacked ? 'stacked' : undefined,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.join('_'),
|
||||
byTypes[LayerTypes.REFERENCELINE] ? 'reference_layer' : undefined,
|
||||
byTypes[LayerTypes.ANNOTATIONS] ? 'annotation_layer' : undefined,
|
||||
byTypes[LayerTypes.DATA] > 1 ? 'multiple_data_layers' : undefined,
|
||||
byTypes.mixedXY ? 'mixed_xy' : undefined,
|
||||
]
|
||||
.filter(Boolean)
|
||||
.map((item) => `render_${originatingApp}_${item}`);
|
||||
}
|
||||
};
|
||||
|
||||
export const getXyChartRenderer = ({
|
||||
getStartDeps,
|
||||
}: XyChartRendererDeps): ExpressionRenderDefinition<XYChartProps> => ({
|
||||
|
@ -48,6 +101,8 @@ export const getXyChartRenderer = ({
|
|||
validate: () => undefined,
|
||||
reuseDomNode: true,
|
||||
render: async (domNode: Element, config: XYChartProps, handlers) => {
|
||||
const deps = await getStartDeps();
|
||||
|
||||
handlers.onDestroy(() => ReactDOM.unmountComponentAtNode(domNode));
|
||||
const onClickValue = (data: FilterEvent['data']) => {
|
||||
handlers.event({ name: 'filter', data });
|
||||
|
@ -55,7 +110,22 @@ export const getXyChartRenderer = ({
|
|||
const onSelectRange = (data: BrushEvent['data']) => {
|
||||
handlers.event({ name: 'brush', data });
|
||||
};
|
||||
const deps = await getStartDeps();
|
||||
|
||||
const renderComplete = () => {
|
||||
const executionContext = handlers.getExecutionContext();
|
||||
const containerType = extractContainerType(executionContext);
|
||||
const visualizationType = extractVisualizationType(executionContext);
|
||||
|
||||
if (deps.usageCollection && containerType && visualizationType) {
|
||||
const uiEvents = extractCounterEvents(visualizationType, config.args.layers);
|
||||
|
||||
if (uiEvents) {
|
||||
deps.usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, uiEvents);
|
||||
}
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
const [{ XYChartReportable }, { calculateMinInterval }] = await Promise.all([
|
||||
import('../components/xy_chart'),
|
||||
|
@ -86,7 +156,7 @@ export const getXyChartRenderer = ({
|
|||
renderMode={handlers.getRenderMode()}
|
||||
syncColors={handlers.isSyncColorsEnabled()}
|
||||
syncTooltips={handlers.isSyncTooltipsEnabled()}
|
||||
renderComplete={() => handlers.done()}
|
||||
renderComplete={renderComplete}
|
||||
/>
|
||||
</div>{' '}
|
||||
</I18nProvider>
|
||||
|
|
|
@ -13,6 +13,7 @@ import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
|||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { CoreSetup, CoreStart, IUiSettingsClient } from '@kbn/core/public';
|
||||
import { EventAnnotationPluginSetup } from '@kbn/event-annotation-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { ExpressionXyPluginSetup, ExpressionXyPluginStart, SetupDeps } from './types';
|
||||
import {
|
||||
xyVisFunction,
|
||||
|
@ -36,6 +37,7 @@ export interface XYPluginStartDependencies {
|
|||
fieldFormats: FieldFormatsStart;
|
||||
charts: ChartsPluginStart;
|
||||
eventAnnotation: EventAnnotationPluginSetup;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
export function getTimeZone(uiSettings: IUiSettingsClient) {
|
||||
|
@ -70,6 +72,7 @@ export class ExpressionXyPlugin {
|
|||
const [coreStart, deps] = await core.getStartServices();
|
||||
const {
|
||||
data,
|
||||
usageCollection,
|
||||
fieldFormats,
|
||||
eventAnnotation,
|
||||
charts: { activeCursor, theme, palettes },
|
||||
|
@ -86,6 +89,7 @@ export class ExpressionXyPlugin {
|
|||
formatFactory: fieldFormats.deserialize,
|
||||
kibanaTheme,
|
||||
theme,
|
||||
usageCollection,
|
||||
activeCursor,
|
||||
paletteService,
|
||||
useLegacyTimeAxis,
|
||||
|
|
|
@ -13,10 +13,12 @@
|
|||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../tsconfig.json" },
|
||||
{ "path": "../../charts/tsconfig.json" },
|
||||
{ "path": "../../../core/tsconfig.json" },
|
||||
{ "path": "../../expressions/tsconfig.json" },
|
||||
{ "path": "../../data/tsconfig.json"},
|
||||
{ "path": "../../usage_collection/tsconfig.json" },
|
||||
{ "path": "../../ui_actions/tsconfig.json" },
|
||||
{ "path": "../../field_formats/tsconfig.json"},
|
||||
{ "path": "../../kibana_utils/tsconfig.json" },
|
||||
|
|
16
src/plugins/chart_expressions/tsconfig.json
Normal file
16
src/plugins/chart_expressions/tsconfig.json
Normal file
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./target/types",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [
|
||||
"common/**/*"
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -231,6 +231,7 @@ export const useDashboardAppState = ({
|
|||
/**
|
||||
* Build the dashboard container embeddable, and apply the incoming embeddable if it exists.
|
||||
*/
|
||||
|
||||
const dashboardContainer = await buildDashboardContainer({
|
||||
...dashboardBuildContext,
|
||||
initialDashboardState,
|
||||
|
@ -238,9 +239,11 @@ export const useDashboardAppState = ({
|
|||
savedDashboard,
|
||||
data,
|
||||
executionContext: {
|
||||
type: 'dashboard',
|
||||
description: savedDashboard.title,
|
||||
},
|
||||
});
|
||||
|
||||
if (canceled || !dashboardContainer) {
|
||||
tryDestroyDashboardContainer(dashboardContainer);
|
||||
return;
|
||||
|
|
|
@ -7,9 +7,9 @@
|
|||
*/
|
||||
|
||||
import { mapValues } from 'lodash';
|
||||
import { AnyExpressionFunctionDefinition } from '../../types';
|
||||
import { ExecutionContext } from '../../../execution/types';
|
||||
import { Datatable } from '../../../expression_types';
|
||||
import type { AnyExpressionFunctionDefinition } from '../../types';
|
||||
import type { ExecutionContext } from '../../../execution/types';
|
||||
import type { Datatable } from '../../../expression_types';
|
||||
|
||||
/**
|
||||
* Takes a function spec and passes in default args,
|
||||
|
@ -24,7 +24,9 @@ export const functionWrapper = <
|
|||
return (
|
||||
context?: Parameters<ExpressionFunctionDefinition['fn']>[0] | null,
|
||||
args: Parameters<ExpressionFunctionDefinition['fn']>[1] = {},
|
||||
handlers: ExecutionContext = {} as ExecutionContext
|
||||
handlers: ExecutionContext = {
|
||||
getExecutionContext: jest.fn(),
|
||||
} as unknown as ExecutionContext
|
||||
) => spec.fn(context, { ...defaultArgs, ...args }, handlers);
|
||||
};
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import type { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
import { ExpressionAstExpression } from '../ast';
|
||||
|
||||
export interface ExpressionRenderDefinition<Config = unknown> {
|
||||
|
@ -99,4 +100,6 @@ export interface IInterpreterRenderHandlers {
|
|||
* Downstream consumers of the uiState handler will need to cast for now.
|
||||
*/
|
||||
uiState?: unknown;
|
||||
|
||||
getExecutionContext(): KibanaExecutionContext | undefined;
|
||||
}
|
||||
|
|
|
@ -115,6 +115,7 @@ export class ExpressionLoader {
|
|||
syncColors: params?.syncColors,
|
||||
syncTooltips: params?.syncTooltips,
|
||||
hasCompatibleActions: params?.hasCompatibleActions,
|
||||
executionContext: params?.executionContext,
|
||||
});
|
||||
this.render$ = this.renderHandler.render$;
|
||||
this.update$ = this.renderHandler.update$;
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
*/
|
||||
|
||||
import { pick } from 'lodash';
|
||||
import { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { PluginInitializerContext, CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import type { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { ExpressionsServiceSetup, ExpressionsServiceStart } from '../common';
|
||||
import {
|
||||
ExpressionsService,
|
||||
|
|
|
@ -11,6 +11,8 @@ import { Observable } from 'rxjs';
|
|||
import { filter } from 'rxjs/operators';
|
||||
import { isNumber } from 'lodash';
|
||||
import { SerializableRecord } from '@kbn/utility-types';
|
||||
import type { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
|
||||
import {
|
||||
ExpressionRenderError,
|
||||
RenderErrorHandlerFnType,
|
||||
|
@ -31,6 +33,7 @@ export interface ExpressionRenderHandlerParams {
|
|||
syncTooltips?: boolean;
|
||||
interactive?: boolean;
|
||||
hasCompatibleActions?: (event: ExpressionRendererEvent) => Promise<boolean>;
|
||||
executionContext?: KibanaExecutionContext;
|
||||
}
|
||||
|
||||
type UpdateValue = IInterpreterRenderUpdateParams<IExpressionLoaderParams>;
|
||||
|
@ -58,6 +61,7 @@ export class ExpressionRenderHandler {
|
|||
syncTooltips,
|
||||
interactive,
|
||||
hasCompatibleActions = async () => false,
|
||||
executionContext,
|
||||
}: ExpressionRenderHandlerParams = {}
|
||||
) {
|
||||
this.element = element;
|
||||
|
@ -84,6 +88,9 @@ export class ExpressionRenderHandler {
|
|||
reload: () => {
|
||||
this.updateSubject.next(null);
|
||||
},
|
||||
getExecutionContext() {
|
||||
return executionContext;
|
||||
},
|
||||
update: (params: UpdateValue) => {
|
||||
this.updateSubject.next(params);
|
||||
},
|
||||
|
|
|
@ -6,9 +6,9 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { NotificationsStart } from '@kbn/core/public';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { ExpressionsService, ExpressionRendererRegistry } from '../../common';
|
||||
import type { NotificationsStart } from '@kbn/core/public';
|
||||
import type { ExpressionsService, ExpressionRendererRegistry } from '../../common';
|
||||
|
||||
export const [getNotifications, setNotifications] =
|
||||
createGetterSetter<NotificationsStart>('Notifications');
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../kibana_utils/tsconfig.json" },
|
||||
{ "path": "../inspector/tsconfig.json" },
|
||||
{ "path": "../field_formats/tsconfig.json" }
|
||||
{ "path": "../field_formats/tsconfig.json" },
|
||||
{ "path": "../usage_collection/tsconfig.json" }
|
||||
]
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ export const defaultHandlers: IInterpreterRenderHandlers = {
|
|||
isSyncColorsEnabled: () => false,
|
||||
isSyncTooltipsEnabled: () => false,
|
||||
isInteractive: () => true,
|
||||
getExecutionContext: () => undefined,
|
||||
done: action('done'),
|
||||
onDestroy: action('onDestroy'),
|
||||
reload: action('reload'),
|
||||
|
|
|
@ -34,7 +34,7 @@ export const getGoalVisTypeDefinition = (
|
|||
addTooltip: true,
|
||||
addLegend: false,
|
||||
isDisplayWarning: false,
|
||||
type: 'gauge',
|
||||
type: 'goal',
|
||||
gauge: {
|
||||
verticalSplit: false,
|
||||
autoExtend: false,
|
||||
|
|
|
@ -33,6 +33,7 @@ describe('TableVisualizationComponent', () => {
|
|||
},
|
||||
tables: [],
|
||||
};
|
||||
const renderComplete = jest.fn();
|
||||
const visConfig = {} as unknown as TableVisConfig;
|
||||
|
||||
it('should render the basic table', () => {
|
||||
|
@ -42,6 +43,7 @@ describe('TableVisualizationComponent', () => {
|
|||
handlers={handlers}
|
||||
visData={visData}
|
||||
visConfig={visConfig}
|
||||
renderComplete={renderComplete}
|
||||
/>
|
||||
);
|
||||
expect(useUiState).toHaveBeenLastCalledWith(handlers.uiState);
|
||||
|
@ -58,6 +60,7 @@ describe('TableVisualizationComponent', () => {
|
|||
tables: [],
|
||||
}}
|
||||
visConfig={visConfig}
|
||||
renderComplete={renderComplete}
|
||||
/>
|
||||
);
|
||||
expect(useUiState).toHaveBeenLastCalledWith(handlers.uiState);
|
||||
|
|
|
@ -9,7 +9,6 @@
|
|||
import './table_visualization.scss';
|
||||
import React, { useLayoutEffect } from 'react';
|
||||
import classNames from 'classnames';
|
||||
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { IInterpreterRenderHandlers } from '@kbn/expressions-plugin';
|
||||
import type { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
|
@ -22,6 +21,7 @@ import { useUiState } from '../utils';
|
|||
interface TableVisualizationComponentProps {
|
||||
core: CoreStart;
|
||||
handlers: IInterpreterRenderHandlers;
|
||||
renderComplete: () => void;
|
||||
visData: TableVisData;
|
||||
visConfig: TableVisConfig;
|
||||
}
|
||||
|
@ -31,13 +31,14 @@ const TableVisualizationComponent = ({
|
|||
handlers,
|
||||
visData: { direction, table, tables },
|
||||
visConfig,
|
||||
renderComplete,
|
||||
}: TableVisualizationComponentProps) => {
|
||||
useLayoutEffect(() => {
|
||||
// Temporary solution: DataGrid should provide onRender callback
|
||||
setTimeout(() => {
|
||||
handlers.done();
|
||||
renderComplete();
|
||||
}, 300);
|
||||
}, [handlers]);
|
||||
}, [renderComplete]);
|
||||
|
||||
const uiStateProps = useUiState(handlers.uiState as PersistedState);
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
import { CoreSetup, CoreStart, Plugin } from '@kbn/core/public';
|
||||
import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/public';
|
||||
import { VisualizationsSetup } from '@kbn/visualizations-plugin/public';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { setFormatService } from './services';
|
||||
|
@ -25,6 +25,7 @@ export interface TablePluginSetupDependencies {
|
|||
/** @internal */
|
||||
export interface TablePluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
|
|
@ -16,8 +16,8 @@ export const registerTableVis = async (
|
|||
core: CoreSetup<TablePluginStartDependencies>,
|
||||
{ expressions, visualizations }: TablePluginSetupDependencies
|
||||
) => {
|
||||
const [coreStart] = await core.getStartServices();
|
||||
const [coreStart, { usageCollection }] = await core.getStartServices();
|
||||
expressions.registerFunction(createTableVisFn);
|
||||
expressions.registerRenderer(getTableVisRenderer(coreStart));
|
||||
expressions.registerRenderer(getTableVisRenderer(coreStart, usageCollection));
|
||||
visualizations.createBaseVisualization(tableVisTypeDefinition);
|
||||
};
|
||||
|
|
|
@ -7,7 +7,11 @@
|
|||
*/
|
||||
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
export const [getFormatService, setFormatService] =
|
||||
createGetterSetter<DataPublicPluginStart['fieldFormats']>('table data.fieldFormats');
|
||||
|
||||
export const [getUsageCollectionStart, setUsageCollectionStart] =
|
||||
createGetterSetter<UsageCollectionStart>('UsageCollection', false);
|
||||
|
|
|
@ -9,17 +9,34 @@
|
|||
import React, { lazy } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { CoreStart } from '@kbn/core/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { CoreStart, KibanaExecutionContext } from '@kbn/core/public';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common/expression_renderers';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { TableVisRenderValue } from './table_vis_fn';
|
||||
|
||||
const TableVisualizationComponent = lazy(() => import('./components/table_visualization'));
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const getTableVisRenderer: (
|
||||
core: CoreStart
|
||||
) => ExpressionRenderDefinition<TableVisRenderValue> = (core) => ({
|
||||
core: CoreStart,
|
||||
usageCollection?: UsageCollectionStart
|
||||
) => ExpressionRenderDefinition<TableVisRenderValue> = (core, usageCollection) => ({
|
||||
name: 'table_vis',
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visData, visConfig }, handlers) => {
|
||||
|
@ -30,11 +47,28 @@ export const getTableVisRenderer: (
|
|||
const showNoResult =
|
||||
visData.table?.rows.length === 0 || (!visData.table && visData.tables.length === 0);
|
||||
|
||||
const renderCompete = () => {
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
const visualizationType = 'agg_based';
|
||||
|
||||
if (usageCollection && containerType) {
|
||||
const counterEvents = [
|
||||
`render_${visualizationType}_table`,
|
||||
!visData.table ? `render_${visualizationType}_table_split` : undefined,
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, counterEvents);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<VisualizationContainer
|
||||
data-test-subj="tbvChartContainer"
|
||||
handlers={handlers}
|
||||
renderComplete={renderCompete}
|
||||
showNoResult={showNoResult}
|
||||
>
|
||||
<TableVisualizationComponent
|
||||
|
@ -42,6 +76,7 @@ export const getTableVisRenderer: (
|
|||
handlers={handlers}
|
||||
visData={visData}
|
||||
visConfig={visConfig}
|
||||
renderComplete={renderCompete}
|
||||
/>
|
||||
</VisualizationContainer>
|
||||
</KibanaThemeProvider>,
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"ui": true,
|
||||
"requiredPlugins": ["visualizations", "data", "expressions", "charts", "dataViews", "fieldFormats"],
|
||||
"requiredBundles": ["kibanaUtils", "kibanaReact", "visDefaultEditor"],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
"githubTeam": "kibana-vis-editors"
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
import type { ISearchStart } from '@kbn/data-plugin/public';
|
||||
import type { DataViewsContract } from '@kbn/data-views-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
|
||||
export const [getIndexPatterns, setIndexPatterns] =
|
||||
|
@ -21,3 +22,8 @@ export const [getCharts, setCharts] = createGetterSetter<ChartsPluginStart>('Cha
|
|||
|
||||
export const [getFieldFormats, setFieldFormats] =
|
||||
createGetterSetter<FieldFormatsStart>('FieldFormats');
|
||||
|
||||
export const [getUsageCollection, setUsageCollection] = createGetterSetter<UsageCollectionStart>(
|
||||
'UsageCollection',
|
||||
false
|
||||
);
|
||||
|
|
|
@ -26,6 +26,7 @@ import type { VisualizationsSetup } from '@kbn/visualizations-plugin/public';
|
|||
import type { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
|
||||
import { FieldFormatsStart } from '@kbn/field-formats-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { getTimelionVisualizationConfig } from './timelion_vis_fn';
|
||||
import { getTimelionVisDefinition } from './timelion_vis_type';
|
||||
import {
|
||||
|
@ -33,6 +34,7 @@ import {
|
|||
setDataSearch,
|
||||
setCharts,
|
||||
setFieldFormats,
|
||||
setUsageCollection,
|
||||
} from './helpers/plugin_services';
|
||||
|
||||
import { getArgValueSuggestions } from './helpers/arg_value_suggestions';
|
||||
|
@ -62,6 +64,7 @@ export interface TimelionVisStartDependencies {
|
|||
dataViews: DataViewsPublicPluginStart;
|
||||
charts: ChartsPluginStart;
|
||||
fieldFormats: FieldFormatsStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @public */
|
||||
|
@ -99,13 +102,17 @@ export class TimelionVisPlugin
|
|||
|
||||
public start(
|
||||
core: CoreStart,
|
||||
{ data, charts, dataViews, fieldFormats }: TimelionVisStartDependencies
|
||||
{ data, charts, dataViews, fieldFormats, usageCollection }: TimelionVisStartDependencies
|
||||
) {
|
||||
setIndexPatterns(dataViews);
|
||||
setDataSearch(data.search);
|
||||
setCharts(charts);
|
||||
setFieldFormats(fieldFormats);
|
||||
|
||||
if (usageCollection) {
|
||||
setUsageCollection(usageCollection);
|
||||
}
|
||||
|
||||
return {
|
||||
getArgValueSuggestions,
|
||||
};
|
||||
|
|
|
@ -13,12 +13,30 @@ import { ExpressionRenderDefinition } from '@kbn/expressions-plugin';
|
|||
import { RangeFilterParams } from '@kbn/es-query';
|
||||
import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { KibanaExecutionContext } from '@kbn/core/public';
|
||||
import { TimelionVisDependencies } from './plugin';
|
||||
import { TimelionRenderValue } from './timelion_vis_fn';
|
||||
import { getUsageCollection } from './helpers/plugin_services';
|
||||
|
||||
const LazyTimelionVisComponent = lazy(() =>
|
||||
import('./async_services').then(({ TimelionVisComponent }) => ({ default: TimelionVisComponent }))
|
||||
);
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const getTimelionVisRenderer: (
|
||||
deps: TimelionVisDependencies
|
||||
) => ExpressionRenderDefinition<TimelionRenderValue> = (deps) => ({
|
||||
|
@ -51,8 +69,26 @@ export const getTimelionVisRenderer: (
|
|||
});
|
||||
};
|
||||
|
||||
const renderComplete = () => {
|
||||
const usageCollection = getUsageCollection();
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
|
||||
if (usageCollection && containerType) {
|
||||
usageCollection.reportUiCounter(
|
||||
containerType,
|
||||
METRIC_TYPE.COUNT,
|
||||
`render_agg_based_timelion`
|
||||
);
|
||||
}
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<VisualizationContainer handlers={handlers} showNoResult={showNoResult}>
|
||||
<VisualizationContainer
|
||||
renderComplete={renderComplete}
|
||||
handlers={handlers}
|
||||
showNoResult={showNoResult}
|
||||
>
|
||||
<KibanaThemeProvider theme$={deps.theme.theme$}>
|
||||
<KibanaContextProvider services={{ ...deps }}>
|
||||
{seriesList && (
|
||||
|
@ -60,7 +96,7 @@ export const getTimelionVisRenderer: (
|
|||
interval={visParams.interval}
|
||||
ariaLabel={visParams.ariaLabel}
|
||||
seriesList={seriesList}
|
||||
renderComplete={handlers.done}
|
||||
renderComplete={renderComplete}
|
||||
onBrushEvent={onBrushEvent}
|
||||
syncTooltips={syncTooltips}
|
||||
/>
|
||||
|
|
|
@ -12,6 +12,7 @@ import { VisualizationsSetup } from '@kbn/visualizations-plugin/public';
|
|||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { EditorController, TSVB_EDITOR_NAME } from './application/editor_controller';
|
||||
|
||||
import { createMetricsFn } from './metrics_fn';
|
||||
|
@ -24,6 +25,7 @@ import {
|
|||
setDataStart,
|
||||
setDataViewsStart,
|
||||
setCharts,
|
||||
setUsageCollectionStart,
|
||||
} from './services';
|
||||
import { getTimeseriesVisRenderer } from './timeseries_vis_renderer';
|
||||
|
||||
|
@ -38,6 +40,7 @@ export interface MetricsPluginStartDependencies {
|
|||
data: DataPublicPluginStart;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
charts: ChartsPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
@ -61,12 +64,18 @@ export class MetricsPlugin implements Plugin<void, void> {
|
|||
visualizations.createBaseVisualization(metricsVisDefinition);
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { data, charts, dataViews }: MetricsPluginStartDependencies) {
|
||||
public start(
|
||||
core: CoreStart,
|
||||
{ data, charts, dataViews, usageCollection }: MetricsPluginStartDependencies
|
||||
) {
|
||||
setCharts(charts);
|
||||
setI18n(core.i18n);
|
||||
setFieldFormats(data.fieldFormats);
|
||||
setDataStart(data);
|
||||
setDataViewsStart(dataViews);
|
||||
setCoreStart(core);
|
||||
if (usageCollection) {
|
||||
setUsageCollectionStart(usageCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,11 +6,12 @@
|
|||
* Side Public License, v 1.
|
||||
*/
|
||||
|
||||
import { I18nStart, IUiSettingsClient, CoreStart } from '@kbn/core/public';
|
||||
import type { I18nStart, IUiSettingsClient, CoreStart } from '@kbn/core/public';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import type { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
export const [getUISettings, setUISettings] = createGetterSetter<IUiSettingsClient>('UISettings');
|
||||
|
||||
|
@ -27,3 +28,6 @@ export const [getDataViewsStart, setDataViewsStart] =
|
|||
export const [getI18n, setI18n] = createGetterSetter<I18nStart>('I18n');
|
||||
|
||||
export const [getCharts, setCharts] = createGetterSetter<ChartsPluginStart>('ChartsPluginStart');
|
||||
|
||||
export const [getUsageCollectionStart, setUsageCollectionStart] =
|
||||
createGetterSetter<UsageCollectionStart>('UsageCollection', false);
|
||||
|
|
|
@ -9,14 +9,16 @@
|
|||
import React, { lazy } from 'react';
|
||||
import { get } from 'lodash';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public';
|
||||
import { IUiSettingsClient, KibanaExecutionContext, ThemeServiceStart } from '@kbn/core/public';
|
||||
|
||||
import { VisualizationContainer, PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
|
||||
import type { ExpressionRenderDefinition } from '@kbn/expressions-plugin/common';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { getUsageCollectionStart } from './services';
|
||||
import { TIME_RANGE_DATA_MODES } from '../common/enums';
|
||||
import type { TimeseriesVisData } from '../common/types';
|
||||
import { isVisTableData } from '../common/vis_data_utils';
|
||||
|
||||
|
@ -36,6 +38,20 @@ const checkIfDataExists = (visData: TimeseriesVisData | {}, model: TimeseriesVis
|
|||
return false;
|
||||
};
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const getTimeseriesVisRenderer: (deps: {
|
||||
uiSettings: IUiSettingsClient;
|
||||
theme: ThemeServiceStart;
|
||||
|
@ -49,12 +65,39 @@ export const getTimeseriesVisRenderer: (deps: {
|
|||
const { visParams: model, visData, syncColors, syncTooltips } = config;
|
||||
const showNoResult = !checkIfDataExists(visData, model);
|
||||
|
||||
const { triggerTSVBtoLensConfiguration } = await import('./trigger_action');
|
||||
const canNavigateToLens = await triggerTSVBtoLensConfiguration(model);
|
||||
|
||||
const renderComplete = () => {
|
||||
const usageCollection = getUsageCollectionStart();
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
const visualizationType = 'tsvb';
|
||||
|
||||
if (usageCollection && containerType) {
|
||||
const counterEvents = [
|
||||
`render_${visualizationType}_${model.type}`,
|
||||
model.use_kibana_indexes === false
|
||||
? `render_${visualizationType}_index_pattern_string`
|
||||
: undefined,
|
||||
model.time_range_mode === TIME_RANGE_DATA_MODES.LAST_VALUE
|
||||
? `render_${visualizationType}_last_value`
|
||||
: undefined,
|
||||
canNavigateToLens ? `render_${visualizationType}_convertable` : undefined,
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, counterEvents);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<I18nProvider>
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<VisualizationContainer
|
||||
data-test-subj="timeseriesVis"
|
||||
handlers={handlers}
|
||||
renderComplete={renderComplete}
|
||||
showNoResult={showNoResult}
|
||||
error={get(visData, [model.id, 'error'])}
|
||||
>
|
||||
|
@ -67,9 +110,7 @@ export const getTimeseriesVisRenderer: (deps: {
|
|||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
uiState={handlers.uiState! as PersistedState}
|
||||
initialRender={() => {
|
||||
handlers.done();
|
||||
}}
|
||||
initialRender={renderComplete}
|
||||
/>
|
||||
</VisualizationContainer>
|
||||
</KibanaThemeProvider>
|
||||
|
|
|
@ -14,6 +14,7 @@ import { VisualizationsSetup } from '@kbn/visualizations-plugin/public';
|
|||
import { Setup as InspectorSetup } from '@kbn/inspector-plugin/public';
|
||||
|
||||
import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import {
|
||||
setNotifications,
|
||||
setData,
|
||||
|
@ -22,6 +23,7 @@ import {
|
|||
setUISettings,
|
||||
setDocLinks,
|
||||
setMapsEms,
|
||||
setUsageCollectionStart,
|
||||
} from './services';
|
||||
|
||||
import { createVegaFn } from './vega_fn';
|
||||
|
@ -56,6 +58,7 @@ export interface VegaPluginStartDependencies {
|
|||
data: DataPublicPluginStart;
|
||||
mapsEms: MapsEmsPluginPublicStart;
|
||||
dataViews: DataViewsPublicPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
/** @internal */
|
||||
|
@ -92,11 +95,18 @@ export class VegaPlugin implements Plugin<void, void> {
|
|||
visualizations.createBaseVisualization(createVegaTypeDefinition());
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { data, mapsEms, dataViews }: VegaPluginStartDependencies) {
|
||||
public start(
|
||||
core: CoreStart,
|
||||
{ data, mapsEms, dataViews, usageCollection }: VegaPluginStartDependencies
|
||||
) {
|
||||
setNotifications(core.notifications);
|
||||
setData(data);
|
||||
setDataViews(dataViews);
|
||||
setDocLinks(core.docLinks);
|
||||
setMapsEms(mapsEms);
|
||||
|
||||
if (usageCollection) {
|
||||
setUsageCollectionStart(usageCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
|||
import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { MapsEmsPluginPublicStart } from '@kbn/maps-ems-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
export const [getData, setData] = createGetterSetter<DataPublicPluginStart>('Data');
|
||||
|
||||
|
@ -31,3 +32,6 @@ export const [getInjectedVars, setInjectedVars] = createGetterSetter<{
|
|||
export const getEnableExternalUrls = () => getInjectedVars().enableExternalUrls;
|
||||
|
||||
export const [getDocLinks, setDocLinks] = createGetterSetter<DocLinksStart>('docLinks');
|
||||
|
||||
export const [getUsageCollectionStart, setUsageCollectionStart] =
|
||||
createGetterSetter<UsageCollectionStart>('UsageCollection', false);
|
||||
|
|
|
@ -8,16 +8,32 @@
|
|||
|
||||
import React, { lazy } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { ExpressionRenderDefinition } from '@kbn/expressions-plugin';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
import { VegaVisualizationDependencies } from './plugin';
|
||||
import { getUsageCollectionStart } from './services';
|
||||
import { RenderValue } from './vega_fn';
|
||||
const LazyVegaVisComponent = lazy(() =>
|
||||
import('./async_services').then(({ VegaVisComponent }) => ({ default: VegaVisComponent }))
|
||||
);
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const getVegaVisRenderer: (
|
||||
deps: VegaVisualizationDependencies
|
||||
) => ExpressionRenderDefinition<RenderValue> = (deps) => ({
|
||||
|
@ -27,13 +43,32 @@ export const getVegaVisRenderer: (
|
|||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
const renderComplete = () => {
|
||||
const usageCollection = getUsageCollectionStart();
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
const visualizationType = 'vega';
|
||||
|
||||
if (usageCollection && containerType) {
|
||||
const counterEvents = [
|
||||
`render_${visualizationType}`,
|
||||
visData.useMap ? `render_${visualizationType}_map` : undefined,
|
||||
`render_${visualizationType}_${visData.isVegaLite ? 'lite' : 'normal'}`,
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, counterEvents);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={deps.core.theme.theme$}>
|
||||
<VisualizationContainer handlers={handlers}>
|
||||
<LazyVegaVisComponent
|
||||
deps={deps}
|
||||
fireEvent={handlers.event}
|
||||
renderComplete={handlers.done}
|
||||
renderComplete={renderComplete}
|
||||
renderMode={handlers.getRenderMode()}
|
||||
visData={visData}
|
||||
/>
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"requiredBundles": ["kibanaUtils", "visTypeXy", "visTypePie", "visTypeHeatmap", "visTypeGauge", "fieldFormats", "kibanaReact"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
|
|
|
@ -15,6 +15,8 @@ import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
|||
import { LEGACY_PIE_CHARTS_LIBRARY } from '@kbn/vis-type-pie-plugin/common';
|
||||
import { LEGACY_HEATMAP_CHARTS_LIBRARY } from '@kbn/vis-type-heatmap-plugin/common';
|
||||
import { LEGACY_GAUGE_CHARTS_LIBRARY } from '@kbn/vis-type-gauge-plugin/common';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { setUsageCollectionStart } from './services';
|
||||
import { heatmapVisTypeDefinition } from './heatmap';
|
||||
|
||||
import { createVisTypeVislibVisFn } from './vis_type_vislib_vis_fn';
|
||||
|
@ -35,6 +37,7 @@ export interface VisTypeVislibPluginSetupDependencies {
|
|||
/** @internal */
|
||||
export interface VisTypeVislibPluginStartDependencies {
|
||||
data: DataPublicPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
export type VisTypeVislibCoreSetup = CoreSetup<VisTypeVislibPluginStartDependencies, void>;
|
||||
|
@ -73,9 +76,12 @@ export class VisTypeVislibPlugin
|
|||
}
|
||||
}
|
||||
|
||||
public start(core: CoreStart, { data }: VisTypeVislibPluginStartDependencies) {
|
||||
public start(core: CoreStart, { data, usageCollection }: VisTypeVislibPluginStartDependencies) {
|
||||
setFormatService(data.fieldFormats);
|
||||
setDataActions(data.actions);
|
||||
setTheme(core.theme);
|
||||
if (usageCollection) {
|
||||
setUsageCollectionStart(usageCollection);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
import { ThemeServiceStart } from '@kbn/core/public';
|
||||
import { createGetterSetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
|
||||
export const [getDataActions, setDataActions] =
|
||||
createGetterSetter<DataPublicPluginStart['actions']>('vislib data.actions');
|
||||
|
@ -18,3 +19,6 @@ export const [getFormatService, setFormatService] = createGetterSetter<
|
|||
>('vislib data.fieldFormats');
|
||||
|
||||
export const [getTheme, setTheme] = createGetterSetter<ThemeServiceStart>('vislib theme service');
|
||||
|
||||
export const [getUsageCollectionStart, setUsageCollectionStart] =
|
||||
createGetterSetter<UsageCollectionStart>('UsageCollection', false);
|
||||
|
|
|
@ -9,10 +9,13 @@
|
|||
import $ from 'jquery';
|
||||
import React, { RefObject } from 'react';
|
||||
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { mountReactNode } from '@kbn/core/public/utils';
|
||||
import { ChartsPluginSetup } from '@kbn/charts-plugin/public';
|
||||
import type { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import { IInterpreterRenderHandlers } from '@kbn/expressions-plugin/public';
|
||||
import { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
import { getUsageCollectionStart } from './services';
|
||||
import { VisTypeVislibCoreSetup } from './plugin';
|
||||
import { VisLegend, CUSTOM_LEGEND_VIS_TYPES } from './vislib/components/legend';
|
||||
import { BasicVislibParams } from './types';
|
||||
|
@ -27,6 +30,38 @@ const legendClassName = {
|
|||
|
||||
export type VislibVisController = InstanceType<ReturnType<typeof createVislibVisController>>;
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
const renderComplete = (
|
||||
visParams: BasicVislibParams | PieVisParams,
|
||||
handlers: IInterpreterRenderHandlers
|
||||
) => {
|
||||
const usageCollection = getUsageCollectionStart();
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
|
||||
if (usageCollection && containerType) {
|
||||
usageCollection.reportUiCounter(
|
||||
containerType,
|
||||
METRIC_TYPE.COUNT,
|
||||
`render_agg_based_${visParams.type}`
|
||||
);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
export const createVislibVisController = (
|
||||
core: VisTypeVislibCoreSetup,
|
||||
charts: ChartsPluginSetup
|
||||
|
@ -74,7 +109,7 @@ export const createVislibVisController = (
|
|||
this.chartEl.dataset.vislibChartType = visParams.type;
|
||||
|
||||
if (this.el.clientWidth === 0 || this.el.clientHeight === 0) {
|
||||
handlers.done();
|
||||
renderComplete(visParams, handlers);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -98,7 +133,7 @@ export const createVislibVisController = (
|
|||
this.mountLegend(esResponse, visParams, fireEvent, uiState as PersistedState);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
renderComplete(visParams, handlers);
|
||||
});
|
||||
|
||||
this.removeListeners = () => {
|
||||
|
|
|
@ -3,8 +3,9 @@
|
|||
"version": "kibana",
|
||||
"ui": true,
|
||||
"server": true,
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations", "usageCollection"],
|
||||
"requiredPlugins": ["charts", "data", "expressions", "visualizations"],
|
||||
"requiredBundles": ["kibanaUtils", "visDefaultEditor", "kibanaReact"],
|
||||
"optionalPlugins": ["usageCollection"],
|
||||
"extraPublicDirs": ["common/index"],
|
||||
"owner": {
|
||||
"name": "Vis Editors",
|
||||
|
|
|
@ -11,7 +11,8 @@ import { Plugin as ExpressionsPublicPlugin } from '@kbn/expressions-plugin/publi
|
|||
import { VisualizationsSetup, VisualizationsStart } from '@kbn/visualizations-plugin/public';
|
||||
import { ChartsPluginSetup, ChartsPluginStart } from '@kbn/charts-plugin/public';
|
||||
import { DataPublicPluginStart } from '@kbn/data-plugin/public';
|
||||
import { UsageCollectionSetup } from '@kbn/usage-collection-plugin/public';
|
||||
import { UsageCollectionSetup, UsageCollectionStart } from '@kbn/usage-collection-plugin/public';
|
||||
import { createStartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import {
|
||||
setDataActions,
|
||||
setFormatService,
|
||||
|
@ -46,6 +47,7 @@ export interface VisTypeXyPluginStartDependencies {
|
|||
visualizations: VisualizationsStart;
|
||||
data: DataPublicPluginStart;
|
||||
charts: ChartsPluginStart;
|
||||
usageCollection?: UsageCollectionStart;
|
||||
}
|
||||
|
||||
type VisTypeXyCoreSetup = CoreSetup<VisTypeXyPluginStartDependencies, VisTypeXyPluginStart>;
|
||||
|
@ -68,10 +70,14 @@ export class VisTypeXyPlugin
|
|||
setThemeService(charts.theme);
|
||||
setPalettesService(charts.palettes);
|
||||
|
||||
const getStartDeps = createStartServicesGetter<
|
||||
VisTypeXyPluginStartDependencies,
|
||||
VisTypeXyPluginStart
|
||||
>(core.getStartServices);
|
||||
|
||||
expressions.registerRenderer(
|
||||
getXYVisRenderer({
|
||||
uiSettings: core.uiSettings,
|
||||
theme: core.theme,
|
||||
getStartDeps,
|
||||
})
|
||||
);
|
||||
expressions.registerFunction(expressionFunctions.visTypeXyVisFn);
|
||||
|
|
|
@ -9,17 +9,20 @@
|
|||
import React, { lazy } from 'react';
|
||||
import { render, unmountComponentAtNode } from 'react-dom';
|
||||
import { I18nProvider } from '@kbn/i18n-react';
|
||||
import { IUiSettingsClient, ThemeServiceStart } from '@kbn/core/public';
|
||||
import { KibanaExecutionContext } from '@kbn/core-execution-context-common';
|
||||
|
||||
import { METRIC_TYPE } from '@kbn/analytics';
|
||||
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
|
||||
import { VisualizationContainer } from '@kbn/visualizations-plugin/public';
|
||||
import type { PersistedState } from '@kbn/visualizations-plugin/public';
|
||||
import type { ExpressionRenderDefinition } from '@kbn/expressions-plugin/public';
|
||||
|
||||
import { LEGACY_TIME_AXIS } from '@kbn/charts-plugin/common';
|
||||
import { StartServicesGetter } from '@kbn/kibana-utils-plugin/public';
|
||||
import type { XyVisType } from '../common';
|
||||
import type { VisComponentType } from './vis_component';
|
||||
import { RenderValue, visName } from './expression_functions/xy_vis_fn';
|
||||
import { VisTypeXyPluginStartDependencies } from './plugin';
|
||||
|
||||
// @ts-ignore
|
||||
const VisComponent = lazy<VisComponentType>(() => import('./vis_component'));
|
||||
|
@ -31,30 +34,70 @@ function shouldShowNoResultsMessage(visData: any, visType: XyVisType): boolean {
|
|||
return Boolean(isZeroHits);
|
||||
}
|
||||
|
||||
/** @internal **/
|
||||
const extractContainerType = (context?: KibanaExecutionContext): string | undefined => {
|
||||
if (context) {
|
||||
const recursiveGet = (item: KibanaExecutionContext): KibanaExecutionContext | undefined => {
|
||||
if (item.type) {
|
||||
return item;
|
||||
} else if (item.child) {
|
||||
return recursiveGet(item.child);
|
||||
}
|
||||
};
|
||||
return recursiveGet(context)?.type;
|
||||
}
|
||||
};
|
||||
|
||||
export const getXYVisRenderer: (deps: {
|
||||
uiSettings: IUiSettingsClient;
|
||||
theme: ThemeServiceStart;
|
||||
}) => ExpressionRenderDefinition<RenderValue> = ({ uiSettings, theme }) => ({
|
||||
getStartDeps: StartServicesGetter<VisTypeXyPluginStartDependencies>;
|
||||
}) => ExpressionRenderDefinition<RenderValue> = ({ getStartDeps }) => ({
|
||||
name: visName,
|
||||
displayName: 'XY visualization',
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, { visData, visConfig, visType, syncColors, syncTooltips }, handlers) => {
|
||||
const { core, plugins } = getStartDeps();
|
||||
const showNoResult = shouldShowNoResultsMessage(visData, visType);
|
||||
|
||||
const renderComplete = () => {
|
||||
// Renaming according to business requirements
|
||||
const visTypeTelemetryMap: Record<string, string> = {
|
||||
histogram: 'vertical_bar',
|
||||
};
|
||||
const containerType = extractContainerType(handlers.getExecutionContext());
|
||||
const visualizationType = 'agg_based';
|
||||
|
||||
if (plugins.usageCollection && containerType) {
|
||||
const hasMixedXY = new Set(visConfig.seriesParams.map((item) => item.type));
|
||||
const counterEvents = [
|
||||
`render_${visualizationType}_${visTypeTelemetryMap[visType] ?? visType}`,
|
||||
hasMixedXY.size > 1 ? `render_${visualizationType}_mixed_xy` : undefined,
|
||||
].filter(Boolean) as string[];
|
||||
|
||||
plugins.usageCollection.reportUiCounter(containerType, METRIC_TYPE.COUNT, counterEvents);
|
||||
}
|
||||
|
||||
handlers.done();
|
||||
};
|
||||
|
||||
handlers.onDestroy(() => unmountComponentAtNode(domNode));
|
||||
|
||||
render(
|
||||
<KibanaThemeProvider theme$={theme.theme$}>
|
||||
<KibanaThemeProvider theme$={core.theme.theme$}>
|
||||
<I18nProvider>
|
||||
<VisualizationContainer handlers={handlers} showNoResult={showNoResult}>
|
||||
<VisualizationContainer
|
||||
renderComplete={renderComplete}
|
||||
handlers={handlers}
|
||||
showNoResult={showNoResult}
|
||||
>
|
||||
<VisComponent
|
||||
visParams={visConfig}
|
||||
visData={visData}
|
||||
renderComplete={handlers.done}
|
||||
renderComplete={renderComplete}
|
||||
fireEvent={handlers.event}
|
||||
uiState={handlers.uiState as PersistedState}
|
||||
syncColors={syncColors}
|
||||
syncTooltips={syncTooltips}
|
||||
useLegacyTimeAxis={uiSettings.get(LEGACY_TIME_AXIS, false)}
|
||||
useLegacyTimeAxis={core.uiSettings.get(LEGACY_TIME_AXIS, false)}
|
||||
/>
|
||||
</VisualizationContainer>
|
||||
</I18nProvider>
|
||||
|
|
|
@ -17,6 +17,7 @@ export interface VisualizationContainerProps {
|
|||
className?: string;
|
||||
children: ReactNode;
|
||||
handlers: IInterpreterRenderHandlers;
|
||||
renderComplete?: () => void;
|
||||
showNoResult?: boolean;
|
||||
error?: string;
|
||||
}
|
||||
|
@ -31,6 +32,7 @@ export const VisualizationContainer = ({
|
|||
handlers,
|
||||
showNoResult = false,
|
||||
error,
|
||||
renderComplete,
|
||||
}: VisualizationContainerProps) => {
|
||||
const classes = classNames('visualization', className);
|
||||
|
||||
|
@ -46,7 +48,9 @@ export const VisualizationContainer = ({
|
|||
{error ? (
|
||||
<VisualizationError onInit={() => handlers.done()} error={error} />
|
||||
) : showNoResult ? (
|
||||
<VisualizationNoResults onInit={() => handlers.done()} />
|
||||
<VisualizationNoResults
|
||||
onInit={() => (renderComplete ? renderComplete() : handlers.done())}
|
||||
/>
|
||||
) : (
|
||||
children
|
||||
)}
|
||||
|
|
|
@ -361,6 +361,7 @@ export class VisualizeEmbeddable
|
|||
onRenderError: (element: HTMLElement, error: ExpressionRenderError) => {
|
||||
this.onContainerError(error);
|
||||
},
|
||||
executionContext: this.getExecutionContext(),
|
||||
});
|
||||
|
||||
this.subscriptions.push(
|
||||
|
@ -464,19 +465,24 @@ export class VisualizeEmbeddable
|
|||
await this.handleVisUpdate();
|
||||
};
|
||||
|
||||
private async updateHandler() {
|
||||
private getExecutionContext() {
|
||||
const parentContext = this.parent?.getInput().executionContext || getExecutionContext().get();
|
||||
const child: KibanaExecutionContext = {
|
||||
type: 'visualization',
|
||||
type: 'agg_based',
|
||||
name: this.vis.type.name,
|
||||
id: this.vis.id ?? 'new',
|
||||
description: this.vis.title || this.input.title || this.vis.type.name,
|
||||
url: this.output.editUrl,
|
||||
};
|
||||
const context = {
|
||||
|
||||
return {
|
||||
...parentContext,
|
||||
child,
|
||||
};
|
||||
}
|
||||
|
||||
private async updateHandler() {
|
||||
const context = this.getExecutionContext();
|
||||
|
||||
const expressionParams: IExpressionLoaderParams = {
|
||||
searchContext: {
|
||||
|
|
|
@ -30,6 +30,9 @@ export default function ({ getService, getPageObjects }: PluginFunctionalProvide
|
|||
name: 'execution_context_app',
|
||||
// add a non-ASCII symbols to make sure it doesn't break the context propagation mechanism
|
||||
id: 'Visualization☺漢字',
|
||||
meta: {
|
||||
foo: 'какая-то странная мета',
|
||||
},
|
||||
description: 'какое-то странное описание',
|
||||
};
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@ export const defaultHandlers: RendererHandlers = {
|
|||
reload: action('reload'),
|
||||
update: action('update'),
|
||||
event: action('event'),
|
||||
getExecutionContext: () => undefined,
|
||||
};
|
||||
|
||||
/*
|
||||
|
|
|
@ -99,7 +99,13 @@ export const embeddableRendererFactory = (
|
|||
throw new EmbeddableFactoryNotFoundError(embeddableType);
|
||||
}
|
||||
|
||||
const embeddableInput = { ...input, id: uniqueId };
|
||||
const embeddableInput = {
|
||||
...input,
|
||||
id: uniqueId,
|
||||
executionContext: {
|
||||
type: 'canvas',
|
||||
},
|
||||
};
|
||||
|
||||
const embeddablePromise = input.savedObjectId
|
||||
? factory
|
||||
|
|
|
@ -29,6 +29,7 @@ export const createBaseHandlers = (): IInterpreterRenderHandlers => ({
|
|||
isSyncColorsEnabled: () => false,
|
||||
isSyncTooltipsEnabled: () => false,
|
||||
isInteractive: () => true,
|
||||
getExecutionContext: () => undefined,
|
||||
});
|
||||
|
||||
export const createHandlers = (baseHandlers = createBaseHandlers()): RendererHandlers => ({
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue