-
{this.renderControls()}
- {stagingButtons}
+
+
+ {this.renderControls()}
+ {stagingButtons}
+
);
}
diff --git a/src/plugins/input_control_vis/public/index.scss b/src/plugins/input_control_vis/public/index.scss
deleted file mode 100644
index 42fded23d7761..0000000000000
--- a/src/plugins/input_control_vis/public/index.scss
+++ /dev/null
@@ -1,9 +0,0 @@
-// Prefix all styles with "icv" to avoid conflicts.
-// Examples
-// icvChart
-// icvChart__legend
-// icvChart__legend--small
-// icvChart__legend-isLoading
-
-@import './components/editor/index';
-@import './components/vis/index';
diff --git a/src/plugins/input_control_vis/public/index.ts b/src/plugins/input_control_vis/public/index.ts
index 8edd3fd9996c3..b6fee12f6d9cb 100644
--- a/src/plugins/input_control_vis/public/index.ts
+++ b/src/plugins/input_control_vis/public/index.ts
@@ -17,8 +17,6 @@
* under the License.
*/
-import './index.scss';
-
import { PluginInitializerContext } from '../../../core/public';
import { InputControlVisPlugin as Plugin } from './plugin';
diff --git a/src/plugins/input_control_vis/public/input_control_fn.ts b/src/plugins/input_control_vis/public/input_control_fn.ts
index 1664555b916b6..46fba66264bcb 100644
--- a/src/plugins/input_control_vis/public/input_control_fn.ts
+++ b/src/plugins/input_control_vis/public/input_control_fn.ts
@@ -20,24 +20,25 @@
import { i18n } from '@kbn/i18n';
import { ExpressionFunctionDefinition, Datatable, Render } from '../../expressions/public';
+import { InputControlVisParams } from './types';
interface Arguments {
visConfig: string;
}
-type VisParams = Required
;
-
-interface RenderValue {
+export interface InputControlRenderValue {
visType: 'input_control_vis';
- visConfig: VisParams;
+ visConfig: InputControlVisParams;
}
-export const createInputControlVisFn = (): ExpressionFunctionDefinition<
+export type InputControlExpressionFunctionDefinition = ExpressionFunctionDefinition<
'input_control_vis',
Datatable,
Arguments,
- Render
-> => ({
+ Render
+>;
+
+export const createInputControlVisFn = (): InputControlExpressionFunctionDefinition => ({
name: 'input_control_vis',
type: 'render',
inputTypes: [],
@@ -52,10 +53,10 @@ export const createInputControlVisFn = (): ExpressionFunctionDefinition<
},
},
fn(input, args) {
- const params = JSON.parse(args.visConfig);
+ const params: InputControlVisParams = JSON.parse(args.visConfig);
return {
type: 'render',
- as: 'visualization',
+ as: 'input_control_vis',
value: {
visType: 'input_control_vis',
visConfig: params,
diff --git a/src/plugins/input_control_vis/public/input_control_vis_renderer.tsx b/src/plugins/input_control_vis/public/input_control_vis_renderer.tsx
new file mode 100644
index 0000000000000..6431ed6ebed1e
--- /dev/null
+++ b/src/plugins/input_control_vis/public/input_control_vis_renderer.tsx
@@ -0,0 +1,51 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ExpressionRenderDefinition } from 'src/plugins/expressions';
+import { InputControlVisDependencies } from './plugin';
+import { InputControlRenderValue } from './input_control_fn';
+import type { InputControlVisControllerType } from './vis_controller';
+
+const inputControlVisRegistry = new Map();
+
+export const getInputControlVisRenderer: (
+ deps: InputControlVisDependencies
+) => ExpressionRenderDefinition = (deps) => ({
+ name: 'input_control_vis',
+ reuseDomNode: true,
+ render: async (domNode, { visConfig }, handlers) => {
+ let registeredController = inputControlVisRegistry.get(domNode);
+
+ if (!registeredController) {
+ const { createInputControlVisController } = await import('./vis_controller');
+
+ const Controller = createInputControlVisController(deps, handlers);
+ registeredController = new Controller(domNode);
+ inputControlVisRegistry.set(domNode, registeredController);
+
+ handlers.onDestroy(() => {
+ registeredController?.destroy();
+ inputControlVisRegistry.delete(domNode);
+ });
+ }
+
+ await registeredController.render(visConfig);
+ handlers.done();
+ },
+});
diff --git a/src/plugins/input_control_vis/public/input_control_vis_type.ts b/src/plugins/input_control_vis/public/input_control_vis_type.ts
index 6e33e18c1603b..686327a1ba774 100644
--- a/src/plugins/input_control_vis/public/input_control_vis_type.ts
+++ b/src/plugins/input_control_vis/public/input_control_vis_type.ts
@@ -19,15 +19,14 @@
import { i18n } from '@kbn/i18n';
import { VisGroups, BaseVisTypeOptions } from '../../visualizations/public';
-import { createInputControlVisController } from './vis_controller';
-import { getControlsTab } from './components/editor/controls_tab';
-import { OptionsTab } from './components/editor/options_tab';
+import { getControlsTab, OptionsTabLazy } from './components/editor';
import { InputControlVisDependencies } from './plugin';
+import { toExpressionAst } from './to_ast';
+import { InputControlVisParams } from './types';
export function createInputControlVisTypeDefinition(
deps: InputControlVisDependencies
-): BaseVisTypeOptions {
- const InputControlVisController = createInputControlVisController(deps);
+): BaseVisTypeOptions {
const ControlsTab = getControlsTab(deps);
return {
@@ -41,7 +40,6 @@ export function createInputControlVisTypeDefinition(
defaultMessage: 'Add dropdown menus and range sliders to your dashboard.',
}),
stage: 'experimental',
- visualization: InputControlVisController,
visConfig: {
defaults: {
controls: [],
@@ -64,12 +62,12 @@ export function createInputControlVisTypeDefinition(
title: i18n.translate('inputControl.register.tabs.optionsTitle', {
defaultMessage: 'Options',
}),
- editor: OptionsTab,
+ editor: OptionsTabLazy,
},
],
},
inspectorAdapters: {},
requestHandler: 'none',
- responseHandler: 'none',
+ toExpressionAst,
};
}
diff --git a/src/plugins/input_control_vis/public/plugin.ts b/src/plugins/input_control_vis/public/plugin.ts
index 2c93a529c25b1..afaaa27d74c82 100644
--- a/src/plugins/input_control_vis/public/plugin.ts
+++ b/src/plugins/input_control_vis/public/plugin.ts
@@ -22,6 +22,7 @@ import { DataPublicPluginSetup, DataPublicPluginStart } from 'src/plugins/data/p
import { Plugin as ExpressionsPublicPlugin } from '../../expressions/public';
import { VisualizationsSetup, VisualizationsStart } from '../../visualizations/public';
import { createInputControlVisFn } from './input_control_fn';
+import { getInputControlVisRenderer } from './input_control_vis_renderer';
import { createInputControlVisTypeDefinition } from './input_control_vis_type';
type InputControlVisCoreSetup = CoreSetup;
@@ -76,6 +77,7 @@ export class InputControlVisPlugin implements Plugin {
};
expressions.registerFunction(createInputControlVisFn);
+ expressions.registerRenderer(getInputControlVisRenderer(visualizationDependencies));
visualizations.createBaseVisualization(
createInputControlVisTypeDefinition(visualizationDependencies)
);
diff --git a/src/plugins/input_control_vis/public/to_ast.test.ts b/src/plugins/input_control_vis/public/to_ast.test.ts
new file mode 100644
index 0000000000000..fbeb78ee93a1e
--- /dev/null
+++ b/src/plugins/input_control_vis/public/to_ast.test.ts
@@ -0,0 +1,54 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { Vis } from '../../visualizations/public';
+import { InputControlVisParams } from './types';
+import { toExpressionAst } from './to_ast';
+
+describe('input_control_vis toExpressionAst', () => {
+ const vis = {
+ params: {
+ controls: [
+ {
+ id: '1536977437774',
+ fieldName: 'manufacturer.keyword',
+ parent: '',
+ label: 'Manufacturer',
+ type: 'list',
+ options: {
+ type: 'terms',
+ multiselect: true,
+ dynamicOptions: true,
+ size: 5,
+ order: 'desc',
+ },
+ indexPattern: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f',
+ },
+ ],
+ updateFiltersOnChange: false,
+ useTimeFilter: true,
+ pinFilters: false,
+ },
+ } as Vis;
+
+ it('should build an expression based on vis.params', () => {
+ const expression = toExpressionAst(vis);
+ expect(expression).toMatchSnapshot();
+ });
+});
diff --git a/src/plugins/input_control_vis/public/to_ast.ts b/src/plugins/input_control_vis/public/to_ast.ts
new file mode 100644
index 0000000000000..93c0b4a87cfe6
--- /dev/null
+++ b/src/plugins/input_control_vis/public/to_ast.ts
@@ -0,0 +1,36 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { buildExpression, buildExpressionFunction } from '../../expressions/public';
+import { Vis } from '../../visualizations/public';
+import { InputControlExpressionFunctionDefinition } from './input_control_fn';
+import { InputControlVisParams } from './types';
+
+export const toExpressionAst = (vis: Vis) => {
+ const inputControl = buildExpressionFunction(
+ 'input_control_vis',
+ {
+ visConfig: JSON.stringify(vis.params),
+ }
+ );
+
+ const ast = buildExpression([inputControl]);
+
+ return ast.toAst();
+};
diff --git a/src/plugins/input_control_vis/public/types.ts b/src/plugins/input_control_vis/public/types.ts
new file mode 100644
index 0000000000000..2898ab49590ed
--- /dev/null
+++ b/src/plugins/input_control_vis/public/types.ts
@@ -0,0 +1,27 @@
+/*
+ * Licensed to Elasticsearch B.V. under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Elasticsearch B.V. licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import { ControlParams } from './editor_utils';
+
+export interface InputControlVisParams {
+ controls: ControlParams[];
+ pinFilters: boolean;
+ updateFiltersOnChange: boolean;
+ useTimeFilter: boolean;
+}
diff --git a/src/plugins/input_control_vis/public/vis_controller.tsx b/src/plugins/input_control_vis/public/vis_controller.tsx
index 6f35e17866120..8e762a38671e9 100644
--- a/src/plugins/input_control_vis/public/vis_controller.tsx
+++ b/src/plugins/input_control_vis/public/vis_controller.tsx
@@ -20,20 +20,29 @@
import React from 'react';
import { isEqual } from 'lodash';
import { render, unmountComponentAtNode } from 'react-dom';
-
import { Subscription } from 'rxjs';
+
import { I18nStart } from 'kibana/public';
+import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
+import { VisualizationContainer } from '../../visualizations/public';
+import { FilterManager, Filter } from '../../data/public';
+
import { InputControlVis } from './components/vis/input_control_vis';
import { getControlFactory } from './control/control_factory';
import { getLineageMap } from './lineage';
-import { ControlParams } from './editor_utils';
import { RangeControl } from './control/range_control_factory';
import { ListControl } from './control/list_control_factory';
import { InputControlVisDependencies } from './plugin';
-import { FilterManager, Filter } from '../../data/public';
-import { VisParams, ExprVis } from '../../visualizations/public';
+import { InputControlVisParams } from './types';
-export const createInputControlVisController = (deps: InputControlVisDependencies) => {
+export type InputControlVisControllerType = InstanceType<
+ ReturnType
+>;
+
+export const createInputControlVisController = (
+ deps: InputControlVisDependencies,
+ handlers: IInterpreterRenderHandlers
+) => {
return class InputControlVisController {
private I18nContext?: I18nStart['Context'];
private _isLoaded = false;
@@ -43,9 +52,9 @@ export const createInputControlVisController = (deps: InputControlVisDependencie
filterManager: FilterManager;
updateSubsciption: any;
timeFilterSubscription: Subscription;
- visParams?: VisParams;
+ visParams?: InputControlVisParams;
- constructor(public el: Element, public vis: ExprVis) {
+ constructor(public el: Element) {
this.controls = [];
this.queryBarUpdateHandler = this.updateControlsFromKbn.bind(this);
@@ -63,7 +72,7 @@ export const createInputControlVisController = (deps: InputControlVisDependencie
});
}
- async render(visData: any, visParams: VisParams) {
+ async render(visParams: InputControlVisParams) {
if (!this.I18nContext) {
const [{ i18n }] = await deps.core.getStartServices();
this.I18nContext = i18n.Context;
@@ -71,7 +80,7 @@ export const createInputControlVisController = (deps: InputControlVisDependencie
if (!this._isLoaded || !isEqual(visParams, this.visParams)) {
this.visParams = visParams;
this.controls = [];
- this.controls = await this.initControls();
+ this.controls = await this.initControls(visParams);
this._isLoaded = true;
}
this.drawVis();
@@ -91,34 +100,34 @@ export const createInputControlVisController = (deps: InputControlVisDependencie
render(
-
+
+
+
,
this.el
);
};
- async initControls() {
- const controlParamsList = (this.visParams?.controls as ControlParams[])?.filter(
- (controlParams) => {
- // ignore controls that do not have indexPattern or field
- return controlParams.indexPattern && controlParams.fieldName;
- }
- );
+ async initControls(visParams: InputControlVisParams) {
+ const controlParamsList = visParams.controls.filter((controlParams) => {
+ // ignore controls that do not have indexPattern or field
+ return controlParams.indexPattern && controlParams.fieldName;
+ });
const controlFactoryPromises = controlParamsList.map((controlParams) => {
const factory = getControlFactory(controlParams);
- return factory(controlParams, this.visParams?.useTimeFilter, deps);
+ return factory(controlParams, visParams.useTimeFilter, deps);
});
const controls = await Promise.all(controlFactoryPromises);
diff --git a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap
index 03a355c604c4d..3ff0c83961e2a 100644
--- a/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap
+++ b/src/plugins/visualizations/public/legacy/__snapshots__/build_pipeline.test.ts.snap
@@ -2,8 +2,6 @@
exports[`visualize loader pipeline helpers: build pipeline buildPipeline calls toExpression on vis_type if it exists 1`] = `"kibana | kibana_context | test"`;
-exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles input_control_vis function 1`] = `"input_control_vis visConfig='{\\"some\\":\\"nested\\",\\"data\\":{\\"here\\":true}}' "`;
-
exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function with buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"},\\"bucket\\":1}' "`;
exports[`visualize loader pipeline helpers: build pipeline buildPipelineVisFunction handles region_map function without buckets 1`] = `"regionmap visConfig='{\\"metric\\":{\\"accessor\\":0,\\"label\\":\\"\\",\\"format\\":{},\\"params\\":{},\\"aggType\\":\\"\\"}}' "`;
diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts
index 653542bd8837d..57c58a99f09ea 100644
--- a/src/plugins/visualizations/public/legacy/build_pipeline.test.ts
+++ b/src/plugins/visualizations/public/legacy/build_pipeline.test.ts
@@ -92,15 +92,6 @@ describe('visualize loader pipeline helpers: build pipeline', () => {
uiState = {};
});
- it('handles input_control_vis function', () => {
- const params = {
- some: 'nested',
- data: { here: true },
- };
- const actual = buildPipelineVisFunction.input_control_vis(params, schemasDef, uiState);
- expect(actual).toMatchSnapshot();
- });
-
describe('handles region_map function', () => {
it('without buckets', () => {
const params = { metric: {} };
diff --git a/src/plugins/visualizations/public/legacy/build_pipeline.ts b/src/plugins/visualizations/public/legacy/build_pipeline.ts
index 0c244876ca6a3..29f6ec9b069a7 100644
--- a/src/plugins/visualizations/public/legacy/build_pipeline.ts
+++ b/src/plugins/visualizations/public/legacy/build_pipeline.ts
@@ -219,9 +219,6 @@ export const prepareDimension = (variable: string, data: any) => {
};
export const buildPipelineVisFunction: BuildPipelineVisFunction = {
- input_control_vis: (params) => {
- return `input_control_vis ${prepareJson('visConfig', params)}`;
- },
region_map: (params, schemas) => {
const visConfig = {
...params,