From 0c57670798d9e280d9d1e30efb54c98f1f3a950c Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Tue, 11 Jul 2023 12:03:53 +0200 Subject: [PATCH 1/3] [Lens] remove native renderer --- .../third_party_vis_lens_example/kibana.jsonc | 3 - .../public/visualization.tsx | 23 +- .../lens_configuration_flyout.test.tsx | 2 +- .../datasources/form_based/datapanel.test.tsx | 4 - .../datasources/form_based/form_based.tsx | 209 ++++----------- .../datasources/text_based/datapanel.test.tsx | 3 +- .../text_based/text_based_languages.tsx | 222 +++++++-------- .../config_panel/layer_panel.test.tsx | 36 ++- .../editor_frame/config_panel/layer_panel.tsx | 154 +++++------ .../config_panel/layer_settings.test.tsx | 4 +- .../config_panel/layer_settings.tsx | 7 +- .../editor_frame/data_panel_wrapper.test.tsx | 11 +- .../editor_frame/data_panel_wrapper.tsx | 16 +- .../editor_frame/editor_frame.test.tsx | 54 ++-- .../workspace_panel_wrapper.test.tsx | 8 +- .../workspace_panel_wrapper.tsx | 29 +- ...datasource_mock.ts => datasource_mock.tsx} | 11 +- .../plugins/lens/public/mocks/store_mocks.tsx | 5 +- ...ization_mock.ts => visualization_mock.tsx} | 4 +- .../lens/public/native_renderer/index.ts | 8 - .../native_renderer/native_renderer.test.tsx | 252 ------------------ .../native_renderer/native_renderer.tsx | 66 ----- x-pack/plugins/lens/public/types.ts | 90 +++---- .../datatable/visualization.tsx | 47 +--- .../visualizations/gauge/visualization.tsx | 26 +- .../visualizations/heatmap/visualization.tsx | 26 +- .../legacy_metric/visualization.tsx | 25 +- .../visualizations/metric/visualization.tsx | 36 +-- .../partition/visualization.tsx | 48 +--- .../tagcloud/tagcloud_visualization.tsx | 34 +-- .../visualizations/xy/visualization.tsx | 131 ++------- .../lens/choropleth_chart/visualization.tsx | 20 +- 32 files changed, 424 insertions(+), 1190 deletions(-) rename x-pack/plugins/lens/public/mocks/{datasource_mock.ts => datasource_mock.tsx} (91%) rename x-pack/plugins/lens/public/mocks/{visualization_mock.ts => visualization_mock.tsx} (96%) delete mode 100644 x-pack/plugins/lens/public/native_renderer/index.ts delete mode 100644 x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx delete mode 100644 x-pack/plugins/lens/public/native_renderer/native_renderer.tsx diff --git a/x-pack/examples/third_party_vis_lens_example/kibana.jsonc b/x-pack/examples/third_party_vis_lens_example/kibana.jsonc index 27d9ae28d42b9..90352c4e8fe2d 100644 --- a/x-pack/examples/third_party_vis_lens_example/kibana.jsonc +++ b/x-pack/examples/third_party_vis_lens_example/kibana.jsonc @@ -16,9 +16,6 @@ "developerExamples", "expressions", "fieldFormats" - ], - "requiredBundles": [ - "kibanaReact" ] } } diff --git a/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx b/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx index 83813a590f6c6..e66117cb83bc9 100644 --- a/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx +++ b/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx @@ -166,19 +166,16 @@ export const getRotatingNumberVisualization = ({ return { ...prevState, accessor: undefined }; }, - renderDimensionEditor(domElement, props) { - render( - - - { - props.setState({ ...props.state, color: newColor }); - }} - color={props.state.color} - /> - - , - domElement + DimensionEditorComponent(props) { + return ( + + { + props.setState({ ...props.state, color: newColor }); + }} + color={props.state.color} + /> + ); }, }); diff --git a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.test.tsx b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.test.tsx index 3a14b26f5d9cc..f1a2ba0630993 100644 --- a/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.test.tsx +++ b/x-pack/plugins/lens/public/app_plugin/shared/edit_on_the_fly/lens_configuration_flyout.test.tsx @@ -196,6 +196,7 @@ describe('LensEditConfigurationFlyout', () => { const { instance } = await prepareAndMountComponent(props); expect(instance.find(VisualizationToolbar).prop('activeVisualization')).toMatchInlineSnapshot(` Object { + "DimensionEditorComponent": [MockFunction], "appendLayer": [MockFunction], "clearLayer": [MockFunction], "getConfiguration": [MockFunction] { @@ -414,7 +415,6 @@ describe('LensEditConfigurationFlyout', () => { "initialize": [MockFunction], "removeDimension": [MockFunction], "removeLayer": [MockFunction], - "renderDimensionEditor": [MockFunction], "setDimension": [MockFunction], "switchVisualizationType": [MockFunction], "toExpression": [MockFunction], diff --git a/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx index e583d2fa7d796..01a31f98000f9 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/datapanel.test.tsx @@ -7,7 +7,6 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import { createMockedDragDropContext } from '../../mocks'; import { dataPluginMock } from '@kbn/data-plugin/public/mocks'; import { dataViewPluginMocks, @@ -408,9 +407,6 @@ describe('FormBased Data Panel', () => { dataViews, }), setState: jest.fn(), - dragDropContext: createMockedDragDropContext({ - dragging: { id: '1', humanData: { label: 'Label' } }, - }), dateRange: { fromDate: '2019-01-01', toDate: '2020-01-01' }, frame: getFrameAPIMock({ indexPatterns: indexPatterns as unknown as DataViewsState['indexPatterns'], diff --git a/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx index 533cdb179f64a..98954f601649d 100644 --- a/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx +++ b/x-pack/plugins/lens/public/datasources/form_based/form_based.tsx @@ -6,8 +6,6 @@ */ import React from 'react'; -import { render } from 'react-dom'; -import { I18nProvider } from '@kbn/i18n-react'; import type { CoreStart, SavedObjectReference } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { TimeRange } from '@kbn/es-query'; @@ -16,7 +14,6 @@ import type { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import { flatten, isEqual } from 'lodash'; import type { DataViewsPublicPluginStart, DataView } from '@kbn/data-views-plugin/public'; import type { IndexPatternFieldEditorStart } from '@kbn/data-view-field-editor-plugin/public'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { DataPublicPluginStart, UI_SETTINGS } from '@kbn/data-plugin/public'; import { VisualizeFieldContext } from '@kbn/ui-actions-plugin/public'; import { ChartsPluginSetup } from '@kbn/charts-plugin/public'; @@ -25,7 +22,7 @@ import { FormattedMessage } from '@kbn/i18n-react'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; import { EuiButton } from '@elastic/eui'; import type { SharePluginStart } from '@kbn/share-plugin/public'; -import { ChildDragDropProvider, type DraggingIdentifier } from '@kbn/dom-drag-drop'; +import { type DraggingIdentifier } from '@kbn/dom-drag-drop'; import { DimensionTrigger } from '@kbn/visualization-ui-components/public'; import memoizeOne from 'memoize-one'; import type { @@ -191,7 +188,7 @@ export function getFormBasedDatasource({ dataViewFieldEditor: IndexPatternFieldEditorStart; uiActions: UiActionsStart; }) { - const { uiSettings, settings } = core; + const { uiSettings } = core; const DATASOURCE_ID = 'formBased'; const ALIAS_IDS = ['indexpattern']; @@ -452,68 +449,27 @@ export function getFormBasedDatasource({ searchSessionId ), - renderLayerSettings(domElement, props) { - render( - - - - - - - , - domElement - ); + LayerSettingsComponent(props) { + return ; }, - - renderDataPanel(domElement: Element, props: DatasourceDataPanelProps) { - const { onChangeIndexPattern, dragDropContext, ...otherProps } = props; + DataPanelComponent(props: DatasourceDataPanelProps) { + const { onChangeIndexPattern, ...otherProps } = props; const layerFields = formBasedDatasource?.getSelectedFields?.(props.state); - - render( - - - - - - - - - , - domElement + return ( + ); }, - uniqueLabels(state: FormBasedPrivateState, indexPatternsMap: IndexPatternMap) { const layers = state.layers; const columnLabelMap = {} as Record; @@ -540,115 +496,48 @@ export function getFormBasedDatasource({ return columnLabelMap; }, - renderDimensionTrigger: ( - domElement: Element, - props: DatasourceDimensionTriggerProps - ) => { + DimensionTriggerComponent: (props: DatasourceDimensionTriggerProps) => { const columnLabelMap = formBasedDatasource.uniqueLabels(props.state, props.indexPatterns); const uniqueLabel = columnLabelMap[props.columnId]; const formattedLabel = wrapOnDot(uniqueLabel); - render( - - - - - - - , - domElement - ); + return ; }, - renderDimensionEditor: ( - domElement: Element, - props: DatasourceDimensionEditorProps - ) => { + DimensionEditorComponent: (props: DatasourceDimensionEditorProps) => { const columnLabelMap = formBasedDatasource.uniqueLabels(props.state, props.indexPatterns); - render( - - - - - - - , - domElement + return ( + ); }, - renderLayerPanel: ( - domElement: Element, - props: DatasourceLayerPanelProps - ) => { + LayerPanelComponent: (props: DatasourceLayerPanelProps) => { const { onChangeIndexPattern, ...otherProps } = props; - render( - - - - { - triggerActionOnIndexPatternChange({ - indexPatternId, - state: props.state, - layerId: props.layerId, - uiActions, - }); - onChangeIndexPattern(indexPatternId, DATASOURCE_ID, props.layerId); - }} - {...otherProps} - /> - - - , - domElement + return ( + { + triggerActionOnIndexPatternChange({ + indexPatternId, + state: props.state, + layerId: props.layerId, + uiActions, + }); + onChangeIndexPattern(indexPatternId, DATASOURCE_ID, props.layerId); + }} + {...otherProps} + /> ); }, diff --git a/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx b/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx index 210678fa909f3..001e2d5b99af8 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/datapanel.test.tsx @@ -28,7 +28,7 @@ import { mountWithIntl } from '@kbn/test-jest-helpers'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { createIndexPatternServiceMock } from '../../mocks/data_views_service_mock'; -import { createMockFramePublicAPI, createMockedDragDropContext } from '../../mocks'; +import { createMockFramePublicAPI } from '../../mocks'; import { DataViewsState } from '../../state_management'; const fieldsFromQuery = [ @@ -184,7 +184,6 @@ describe('TextBased Query Languages Data Panel', () => { ]) ), }, - dragDropContext: createMockedDragDropContext(), core, dateRange: { fromDate: 'now-7d', diff --git a/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx index f93efd9835ee2..831bb1501c8fc 100644 --- a/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx +++ b/x-pack/plugins/lens/public/datasources/text_based/text_based_languages.tsx @@ -6,15 +6,12 @@ */ import React from 'react'; -import { render } from 'react-dom'; -import { I18nProvider } from '@kbn/i18n-react'; import { CoreStart } from '@kbn/core/public'; import { i18n } from '@kbn/i18n'; import { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; import type { AggregateQuery } from '@kbn/es-query'; import type { SavedObjectReference } from '@kbn/core/public'; import { EuiFormRow } from '@elastic/eui'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import type { ExpressionsStart, DatatableColumnType } from '@kbn/expressions-plugin/public'; import type { DataViewsPublicPluginStart, DataView } from '@kbn/data-views-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; @@ -22,7 +19,6 @@ import { euiThemeVars } from '@kbn/ui-theme'; import { DimensionTrigger } from '@kbn/visualization-ui-components/public'; import memoizeOne from 'memoize-one'; import { isEqual } from 'lodash'; -import { ChildDragDropProvider } from '@kbn/dom-drag-drop'; import { DatasourceDimensionEditorProps, DatasourceDataPanelProps, @@ -364,31 +360,20 @@ export function getTextBasedDatasource({ ); }, - renderDataPanel(domElement: Element, props: DatasourceDataPanelProps) { + DataPanelComponent(props: DatasourceDataPanelProps) { const layerFields = TextBasedDatasource?.getSelectedFields?.(props.state); - const { dragDropContext, ...otherProps } = props; - render( - - - - - - - , - domElement + return ( + ); }, - renderDimensionTrigger: ( - domElement: Element, - props: DatasourceDimensionTriggerProps - ) => { + DimensionTriggerComponent: (props: DatasourceDimensionTriggerProps) => { const columnLabelMap = TextBasedDatasource.uniqueLabels(props.state, props.indexPatterns); const layer = props.state.layers[props.layerId]; const selectedField = layer?.allColumns?.find((column) => column.columnId === props.columnId); @@ -397,23 +382,18 @@ export function getTextBasedDatasource({ customLabel = selectedField?.fieldName; } - render( - - - {' '} - - , - domElement + return ( + ); }, @@ -421,10 +401,7 @@ export function getTextBasedDatasource({ return []; }, - renderDimensionEditor: ( - domElement: Element, - props: DatasourceDimensionEditorProps - ) => { + DimensionEditorComponent: (props: DatasourceDimensionEditorProps) => { const fields = props.state.fieldList; const selectedField = props.state.layers[props.layerId]?.allColumns?.find( (column) => column.columnId === props.columnId @@ -442,94 +419,81 @@ export function getTextBasedDatasource({ : true, }; }); - render( - - - - { - const meta = fields.find((f) => f.name === choice.field)?.meta; - const newColumn = { - columnId: props.columnId, - fieldName: choice.field, - meta, - }; - return props.setState( - !selectedField - ? { - ...props.state, - layers: { - ...props.state.layers, - [props.layerId]: { - ...props.state.layers[props.layerId], - columns: [...props.state.layers[props.layerId].columns, newColumn], - allColumns: [ - ...props.state.layers[props.layerId].allColumns, - newColumn, - ], - }, + return ( + <> + + { + const meta = fields.find((f) => f.name === choice.field)?.meta; + const newColumn = { + columnId: props.columnId, + fieldName: choice.field, + meta, + }; + return props.setState( + !selectedField + ? { + ...props.state, + layers: { + ...props.state.layers, + [props.layerId]: { + ...props.state.layers[props.layerId], + columns: [...props.state.layers[props.layerId].columns, newColumn], + allColumns: [ + ...props.state.layers[props.layerId].allColumns, + newColumn, + ], }, - } - : { - ...props.state, - layers: { - ...props.state.layers, - [props.layerId]: { - ...props.state.layers[props.layerId], - columns: props.state.layers[props.layerId].columns.map((col) => - col.columnId !== props.columnId - ? col - : { ...col, fieldName: choice.field, meta } - ), - allColumns: props.state.layers[props.layerId].allColumns.map((col) => - col.columnId !== props.columnId - ? col - : { ...col, fieldName: choice.field, meta } - ), - }, + }, + } + : { + ...props.state, + layers: { + ...props.state.layers, + [props.layerId]: { + ...props.state.layers[props.layerId], + columns: props.state.layers[props.layerId].columns.map((col) => + col.columnId !== props.columnId + ? col + : { ...col, fieldName: choice.field, meta } + ), + allColumns: props.state.layers[props.layerId].allColumns.map((col) => + col.columnId !== props.columnId + ? col + : { ...col, fieldName: choice.field, meta } + ), }, - } - ); - }} - /> - - {props.dataSectionExtra && ( -
- {props.dataSectionExtra} -
- )} -
-
, - domElement + }, + } + ); + }} + /> + + {props.dataSectionExtra && ( +
+ {props.dataSectionExtra} +
+ )} + ); }, - renderLayerPanel: ( - domElement: Element, - props: DatasourceLayerPanelProps - ) => { - render( - - - - - , - domElement - ); + LayerPanelComponent: (props: DatasourceLayerPanelProps) => { + return ; }, uniqueLabels(state: TextBasedPrivateState) { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx index 9db931efeda26..bb258c4bd690f 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.test.tsx @@ -390,7 +390,7 @@ describe('LayerPanel', () => { }, ], }); - mockVisualization.renderDimensionEditor = jest.fn(); + mockVisualization.DimensionEditorComponent = jest.fn().mockImplementation(() =>
); const { instance } = await mountWithProvider(); act(() => { @@ -434,14 +434,13 @@ describe('LayerPanel', () => { }); instance.update(); - expect(mockDatasource.renderDimensionEditor).toHaveBeenCalledWith( - expect.any(Element), + expect(mockDatasource.DimensionEditorComponent).toHaveBeenCalledWith( expect.objectContaining({ columnId: 'newid' }) ); const stateFn = - mockDatasource.renderDimensionEditor.mock.calls[ - mockDatasource.renderDimensionEditor.mock.calls.length - 1 - ][1].setState; + mockDatasource.DimensionEditorComponent.mock.calls[ + mockDatasource.DimensionEditorComponent.mock.calls.length - 1 + ][0].setState; act(() => { stateFn( @@ -512,14 +511,13 @@ describe('LayerPanel', () => { }); instance.update(); - expect(mockDatasource.renderDimensionEditor).toHaveBeenCalledWith( - expect.any(Element), + expect(mockDatasource.DimensionEditorComponent).toHaveBeenCalledWith( expect.objectContaining({ columnId: 'y' }) ); const stateFn = - mockDatasource.renderDimensionEditor.mock.calls[ - mockDatasource.renderDimensionEditor.mock.calls.length - 1 - ][1].setState; + mockDatasource.DimensionEditorComponent.mock.calls[ + mockDatasource.DimensionEditorComponent.mock.calls.length - 1 + ][0].setState; act(() => { stateFn( @@ -586,9 +584,9 @@ describe('LayerPanel', () => { expect(instance.find('EuiFlyoutHeader').exists()).toBe(true); const lastArgs = - mockDatasource.renderDimensionEditor.mock.calls[ - mockDatasource.renderDimensionEditor.mock.calls.length - 1 - ][1]; + mockDatasource.DimensionEditorComponent.mock.calls[ + mockDatasource.DimensionEditorComponent.mock.calls.length - 1 + ][0]; // Simulate what is called by the dimension editor act(() => { @@ -597,7 +595,7 @@ describe('LayerPanel', () => { }); }); - expect(mockVisualization.renderDimensionEditor).toHaveBeenCalled(); + expect(mockVisualization.DimensionEditorComponent).toHaveBeenCalled(); }); it('should close the DimensionContainer when the active visualization changes', async () => { @@ -1331,7 +1329,7 @@ describe('LayerPanel', () => { ], }); await mountWithProvider(); - expect(mockDatasource.renderDimensionTrigger).toHaveBeenCalled(); + expect(mockDatasource.DimensionTriggerComponent).toHaveBeenCalled(); }); it('should render visualization dimension trigger if there is no layer datasource', async () => { @@ -1354,14 +1352,14 @@ describe('LayerPanel', () => { framePublicAPI: { ...props.framePublicAPI, datasourceLayers: {} }, }; - mockVisualization.renderDimensionTrigger = jest.fn(); + mockVisualization.DimensionTriggerComponent = jest.fn().mockImplementation(() =>
); mockVisualization.getUniqueLabels = jest.fn(() => ({ x: 'A', })); await mountWithProvider(); - expect(mockDatasource.renderDimensionTrigger).not.toHaveBeenCalled(); - expect(mockVisualization.renderDimensionTrigger).toHaveBeenCalled(); + expect(mockDatasource.DimensionTriggerComponent).not.toHaveBeenCalled(); + expect(mockVisualization.DimensionTriggerComponent).toHaveBeenCalled(); }); // TODO - test user message display diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx index 83f06e84659e1..f957886ce033a 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_panel.tsx @@ -24,7 +24,6 @@ import { DragDropIdentifier, ReorderProvider, DropType } from '@kbn/dom-drag-dro import { DimensionButton, DimensionTrigger } from '@kbn/visualization-ui-components/public'; import { LayerActions } from './layer_actions'; import { IndexPatternServiceAPI } from '../../../data_views_service/service'; -import { NativeRenderer } from '../../../native_renderer'; import { StateSetter, Visualization, @@ -374,8 +373,8 @@ export function LayerPanel( isTextBasedLanguage, hasLayerSettings: Boolean( (Object.values(visualizationLayerSettings).some(Boolean) && - activeVisualization.renderLayerSettings) || - layerDatasource?.renderLayerSettings + activeVisualization.LayerSettingsComponent) || + layerDatasource?.LayerSettingsComponent ), openLayerSettings: () => setPanelSettingsOpen(true), onCloneLayer, @@ -398,7 +397,7 @@ export function LayerPanel( isOnlyLayer, isTextBasedLanguage, visualizationLayerSettings, - layerDatasource?.renderLayerSettings, + layerDatasource?.LayerSettingsComponent, onCloneLayer, onRemoveLayer, ] @@ -438,11 +437,12 @@ export function LayerPanel( )} {props.indexPatternService && - (layerDatasource || activeVisualization.renderLayerPanel) && } + (layerDatasource || activeVisualization.LayerPanelComponent) && ( + + )} {layerDatasource && props.indexPatternService && ( - )} - {activeVisualization.renderLayerPanel && ( - {layerDatasource ? ( - + {layerDatasource.DimensionTriggerComponent({ ...layerDatasourceConfigProps, columnId: accessorConfig.columnId, groupId: group.groupId, filterOperations: group.filterOperations, indexPatterns: dataViews.indexPatterns, - }} - /> + })} + ) : ( <> - {activeVisualization?.renderDimensionTrigger?.({ + {activeVisualization?.DimensionTriggerComponent?.({ columnId, label: columnLabelMap?.[columnId] ?? '', hideTooltip, @@ -705,7 +703,7 @@ export function LayerPanel( })} - {(layerDatasource?.renderLayerSettings || activeVisualization?.renderLayerSettings) && ( + {(layerDatasource?.LayerSettingsComponent || activeVisualization?.LayerSettingsComponent) && ( (settingsPanelRef.current = el)} isOpen={isPanelSettingsOpen} @@ -721,7 +719,7 @@ export function LayerPanel( >
- {layerDatasource?.renderLayerSettings || visualizationLayerSettings.data ? ( + {layerDatasource?.LayerSettingsComponent || visualizationLayerSettings.data ? ( ) : null} - {layerDatasource?.renderLayerSettings && ( + {layerDatasource?.LayerSettingsComponent && ( <> - + )} - {layerDatasource?.renderLayerSettings && visualizationLayerSettings.data ? ( + {layerDatasource?.LayerSettingsComponent && visualizationLayerSettings.data ? ( ) : null} - {activeVisualization?.renderLayerSettings && visualizationLayerSettings.data ? ( - ) : null} - {activeVisualization?.renderLayerSettings && ( - - {activeGroup && activeId && layerDatasource && ( - - ), - }} - /> - )} + {activeGroup && + activeId && + layerDatasource && + layerDatasource.DimensionEditorComponent({ + ...layerDatasourceConfigProps, + core: props.core, + columnId: activeId, + groupId: activeGroup.groupId, + hideGrouping: activeGroup.hideGrouping, + filterOperations: activeGroup.filterOperations, + isMetricDimension: activeGroup?.isMetricDimension, + dimensionGroups, + toggleFullscreen, + isFullscreen, + setState: updateDataLayerState, + supportStaticValue: Boolean(activeGroup.supportStaticValue), + paramEditorCustomProps: activeGroup.paramEditorCustomProps, + enableFormatSelector: activeGroup.enableFormatSelector !== false, + layerType: activeVisualization.getLayerType(layerId, visualizationState), + indexPatterns: dataViews.indexPatterns, + activeData: layerVisualizationConfigProps.activeData, + dataSectionExtra: !isFullscreen && + !activeDimension.isNew && + activeVisualization.DimensionEditorDataExtraComponent && ( + + ), + })} {activeGroup && activeId && !isFullscreen && !activeDimension.isNew && - activeVisualization.renderDimensionEditor && + activeVisualization.DimensionEditorComponent && activeGroup?.enableDimensionEditor && ( <>
-
- {activeVisualization.renderDimensionEditorAdditionalSection && ( - { }); it('should call the custom renderer if available', async () => { - mockVisualization.renderLayerHeader = jest.fn(); + mockVisualization.LayerHeaderComponent = jest.fn().mockImplementation(() =>
); await mountWithProvider(); - expect(mockVisualization.renderLayerHeader).toHaveBeenCalled(); + expect(mockVisualization.LayerHeaderComponent).toHaveBeenCalled(); }); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx index fc88ff2af8bbe..f04b2a93835df 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/config_panel/layer_settings.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -import { NativeRenderer } from '../../../native_renderer'; import { Visualization, VisualizationLayerWidgetProps } from '../../../types'; import { StaticHeader } from '../../../shared_components'; @@ -17,7 +16,7 @@ export function LayerSettings({ activeVisualization: Visualization; layerConfigProps: VisualizationLayerWidgetProps; }) { - if (!activeVisualization.renderLayerHeader) { + if (!activeVisualization.LayerHeaderComponent) { const description = activeVisualization.getDescription(layerConfigProps.state); if (!description) { return null; @@ -25,7 +24,5 @@ export function LayerSettings({ return ; } - return ( - - ); + return ; } diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx index b2ac0786e3302..028c6551d85c9 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.test.tsx @@ -6,7 +6,6 @@ */ import React from 'react'; -import { DragDropIdentifier } from '@kbn/dom-drag-drop'; import { DataPanelWrapper } from './data_panel_wrapper'; import { Datasource, DatasourceDataPanelProps, VisualizationMap } from '../../types'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; @@ -22,11 +21,11 @@ describe('Data Panel Wrapper', () => { let datasourceDataPanelProps: DatasourceDataPanelProps; let lensStore: Awaited>['lensStore']; beforeEach(async () => { - const renderDataPanel = jest.fn(); + const DataPanelComponent = jest.fn().mockImplementation(() =>
); const datasourceMap = { activeDatasource: { - renderDataPanel, + DataPanelComponent, getUsedDataViews: jest.fn(), getLayers: jest.fn(() => []), } as unknown as Datasource, @@ -38,8 +37,8 @@ describe('Data Panel Wrapper', () => { visualizationMap={{} as VisualizationMap} showNoDataPopover={() => {}} core={{} as DatasourceDataPanelProps['core']} - dropOntoWorkspace={(field: DragDropIdentifier) => {}} - hasSuggestionForField={(field: DragDropIdentifier) => true} + dropOntoWorkspace={() => {}} + hasSuggestionForField={() => true} plugins={{ uiActions: {} as UiActionsStart, dataViews: {} as DataViewsPublicPluginStart, @@ -66,7 +65,7 @@ describe('Data Panel Wrapper', () => { lensStore = mountResult.lensStore; - datasourceDataPanelProps = renderDataPanel.mock.calls[0][1] as DatasourceDataPanelProps; + datasourceDataPanelProps = DataPanelComponent.mock.calls[0][0] as DatasourceDataPanelProps; }); describe('setState', () => { diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx index a933f6865f08e..394c301d8baf6 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/data_panel_wrapper.tsx @@ -12,11 +12,10 @@ import { Storage } from '@kbn/kibana-utils-plugin/public'; import { UiActionsStart } from '@kbn/ui-actions-plugin/public'; import { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import { EventAnnotationServiceType } from '@kbn/event-annotation-plugin/public'; -import { useDragDropContext, DragDropIdentifier } from '@kbn/dom-drag-drop'; +import { DragDropIdentifier } from '@kbn/dom-drag-drop'; import memoizeOne from 'memoize-one'; import { isEqual } from 'lodash'; import { Easteregg } from './easteregg'; -import { NativeRenderer } from '../../native_renderer'; import { StateSetter, DatasourceDataPanelProps, @@ -162,7 +161,6 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { const datasourceProps: DatasourceDataPanelProps = { ...externalContext, - dragDropContext: useDragDropContext(), state: activeDatasourceId ? datasourceStates[activeDatasourceId].state : null, setState: setDatasourceState, core: props.core, @@ -187,16 +185,16 @@ export const DataPanelWrapper = memo((props: DataPanelWrapperProps) => { []), ]), }; + const DataPanelComponent = + activeDatasourceId && !datasourceIsLoading + ? props.datasourceMap[activeDatasourceId].DataPanelComponent + : null; return ( <> - {activeDatasourceId && !datasourceIsLoading && ( - + {DataPanelComponent && ( +
{DataPanelComponent(datasourceProps)}
)} ); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx index 8571b2ca347b0..988bb0bb65592 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/editor_frame.test.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React from 'react'; +import React, { useEffect } from 'react'; import { ReactWrapper } from 'enzyme'; // Tests are executed in a jsdom environment who does not have sizing methods, @@ -41,7 +41,7 @@ import { } from '../../mocks'; import { inspectorPluginMock } from '@kbn/inspector-plugin/public/mocks'; import { ReactExpressionRendererType } from '@kbn/expressions-plugin/public'; -import { DragDrop } from '@kbn/dom-drag-drop'; +import { DragDrop, useDragDropContext } from '@kbn/dom-drag-drop'; import { uiActionsPluginMock } from '@kbn/ui-actions-plugin/public/mocks'; import { chartPluginMock } from '@kbn/charts-plugin/public/mocks'; import { expressionsPluginMock } from '@kbn/expressions-plugin/public/mocks'; @@ -177,7 +177,7 @@ describe('editor_frame', () => { }, }, }); - expect(mockDatasource.renderDataPanel).not.toHaveBeenCalled(); + expect(mockDatasource.DataPanelComponent).not.toHaveBeenCalled(); lensStore.dispatch( setState({ datasourceStates: { @@ -190,7 +190,7 @@ describe('editor_frame', () => { }, }) ); - expect(mockDatasource.renderDataPanel).toHaveBeenCalled(); + expect(mockDatasource.DataPanelComponent).toHaveBeenCalled(); }); it('should initialize visualization state and render config panel', async () => { @@ -304,7 +304,7 @@ describe('editor_frame', () => { }, }); const updatedState = {}; - const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1] + const setDatasourceState = (mockDatasource.DataPanelComponent as jest.Mock).mock.calls[0][0] .setState; act(() => { setDatasourceState(updatedState); @@ -334,10 +334,10 @@ describe('editor_frame', () => { }; await mountWithProvider(); - const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1] + const setDatasourceState = (mockDatasource.DataPanelComponent as jest.Mock).mock.calls[0][0] .setState; - mockDatasource.renderDataPanel.mockClear(); + mockDatasource.DataPanelComponent.mockClear(); const updatedState = { title: 'shazm', @@ -346,9 +346,8 @@ describe('editor_frame', () => { setDatasourceState(updatedState); }); - expect(mockDatasource.renderDataPanel).toHaveBeenCalledTimes(1); - expect(mockDatasource.renderDataPanel).toHaveBeenLastCalledWith( - expect.any(Element), + expect(mockDatasource.DataPanelComponent).toHaveBeenCalledTimes(1); + expect(mockDatasource.DataPanelComponent).toHaveBeenLastCalledWith( expect.objectContaining({ state: updatedState, }) @@ -385,7 +384,7 @@ describe('editor_frame', () => { }; mockDatasource.getPublicAPI.mockReturnValue(updatedPublicAPI); - const setDatasourceState = (mockDatasource.renderDataPanel as jest.Mock).mock.calls[0][1] + const setDatasourceState = (mockDatasource.DataPanelComponent as jest.Mock).mock.calls[0][0] .setState; act(() => { setDatasourceState({}); @@ -722,8 +721,7 @@ describe('editor_frame', () => { state: suggestionVisState, }) ); - expect(mockDatasource.renderDataPanel).toHaveBeenLastCalledWith( - expect.any(Element), + expect(mockDatasource.DataPanelComponent).toHaveBeenLastCalledWith( expect.objectContaining({ state: newDatasourceState, }) @@ -820,19 +818,7 @@ describe('editor_frame', () => { getDatasourceSuggestionsForField: () => [generateSuggestion()], getDatasourceSuggestionsFromCurrentState: () => [generateSuggestion()], getDatasourceSuggestionsForVisualizeField: () => [generateSuggestion()], - renderDataPanel: (_element, { dragDropContext: [{ dragging }, dndDispatch] }) => { - if (!dragging || dragging.id !== 'draggedField') { - dndDispatch({ - type: 'startDragging', - payload: { - dragging: { - id: 'draggedField', - humanData: { label: 'draggedField' }, - }, - }, - }); - } - }, + DataPanelComponent: jest.fn().mockImplementation(() =>
), }, }, @@ -863,7 +849,7 @@ describe('editor_frame', () => { id: '1', humanData: { label: 'draggedField' }, }, - 'field_replace' + 'field_add' ); }); @@ -927,8 +913,9 @@ describe('editor_frame', () => { getDatasourceSuggestionsForField: () => [generateSuggestion()], getDatasourceSuggestionsFromCurrentState: () => [generateSuggestion()], getDatasourceSuggestionsForVisualizeField: () => [generateSuggestion()], - renderDataPanel: (_element, { dragDropContext: [{ dragging }, dndDispatch] }) => { - if (!dragging || dragging.id !== 'draggedField') { + DataPanelComponent: jest.fn().mockImplementation(() => { + const [, dndDispatch] = useDragDropContext(); + useEffect(() => { dndDispatch({ type: 'startDragging', payload: { @@ -938,15 +925,16 @@ describe('editor_frame', () => { }, }, }); - } - }, + }, [dndDispatch]); + return
; + }), }, }, - ExpressionRenderer: expressionRendererMock, } as EditorFrameProps; instance = (await mountWithProvider()).instance; + instance.update(); act(() => { @@ -959,7 +947,7 @@ describe('editor_frame', () => { label: 'label', }, }, - 'field_replace' + 'field_add' ); }); diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx index 700fe7f96bf84..9811b59b7b30c 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.test.tsx @@ -51,7 +51,7 @@ describe('workspace_panel_wrapper', () => { }); it('should call the toolbar renderer if provided', async () => { - const renderToolbarMock = jest.fn(); + const ToolbarComponentMock = jest.fn(() => null); const visState = { internalState: 123 }; await mountWithProvider( { visualizationState={visState} children={} visualizationId="myVis" - visualizationMap={{ myVis: { ...mockVisualization, renderToolbar: renderToolbarMock } }} + visualizationMap={{ + myVis: { ...mockVisualization, ToolbarComponent: ToolbarComponentMock }, + }} datasourceMap={{}} datasourceStates={{}} isFullscreen={false} @@ -74,7 +76,7 @@ describe('workspace_panel_wrapper', () => { } ); - expect(renderToolbarMock).toHaveBeenCalledWith(expect.any(Element), { + expect(ToolbarComponentMock).toHaveBeenCalledWith({ state: visState, frame: mockFrameAPI, setState: expect.anything(), diff --git a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx index 064b268209aea..9469a903131bd 100644 --- a/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx +++ b/x-pack/plugins/lens/public/editor_frame_service/editor_frame/workspace_panel/workspace_panel_wrapper.tsx @@ -19,7 +19,6 @@ import { Visualization, } from '../../../types'; import { DONT_CLOSE_DIMENSION_CONTAINER_ON_CLICK_CLASS } from '../../../utils'; -import { NativeRenderer } from '../../../native_renderer'; import { ChartSwitch } from './chart_switch'; import { MessageList } from './message_list'; import { @@ -59,37 +58,37 @@ export function VisualizationToolbar(props: { const { activeDatasourceId, visualization, datasourceStates } = useLensSelector( (state) => state.lens ); + const { activeVisualization, onUpdateStateCb } = props; const setVisualizationState = useCallback( (newState: unknown) => { - if (!props.activeVisualization) { + if (!activeVisualization) { return; } dispatchLens( updateVisualizationState({ - visualizationId: props.activeVisualization.id, + visualizationId: activeVisualization.id, newState, }) ); - if (activeDatasourceId && props.onUpdateStateCb) { + if (activeDatasourceId && onUpdateStateCb) { const dsState = datasourceStates[activeDatasourceId].state; - props.onUpdateStateCb?.(dsState, newState); + onUpdateStateCb?.(dsState, newState); } }, - [activeDatasourceId, datasourceStates, dispatchLens, props] + [activeDatasourceId, datasourceStates, dispatchLens, activeVisualization, onUpdateStateCb] ); + const ToolbarComponent = props.activeVisualization?.ToolbarComponent; + return ( <> - {props.activeVisualization && props.activeVisualization.renderToolbar && ( + {ToolbarComponent && ( - + {ToolbarComponent({ + frame: props.framePublicAPI, + state: visualization.state, + setState: setVisualizationState, + })} )} diff --git a/x-pack/plugins/lens/public/mocks/datasource_mock.ts b/x-pack/plugins/lens/public/mocks/datasource_mock.tsx similarity index 91% rename from x-pack/plugins/lens/public/mocks/datasource_mock.ts rename to x-pack/plugins/lens/public/mocks/datasource_mock.tsx index 9417837a14b84..e4f9f5c88fdc1 100644 --- a/x-pack/plugins/lens/public/mocks/datasource_mock.ts +++ b/x-pack/plugins/lens/public/mocks/datasource_mock.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import React from 'react'; import { DatasourcePublicAPI, Datasource } from '../types'; export type DatasourceMock = jest.Mocked & { @@ -44,8 +44,6 @@ export function createMockDatasource( getRenderEventCounters: jest.fn((_state) => []), getPublicAPI: jest.fn().mockReturnValue(publicAPIMock), initialize: jest.fn((_state?) => {}), - renderDataPanel: jest.fn(), - renderLayerPanel: jest.fn(), toExpression: jest.fn((_frame, _state, _indexPatterns, dateRange, nowInstant) => null), insertLayer: jest.fn((_state, _newLayerId) => ({})), removeLayer: jest.fn((state, layerId) => ({ newState: state, removedLayerIds: [layerId] })), @@ -53,8 +51,6 @@ export function createMockDatasource( removeColumn: jest.fn((props) => {}), getLayers: jest.fn((_state) => []), uniqueLabels: jest.fn((_state, dataViews) => ({})), - renderDimensionTrigger: jest.fn(), - renderDimensionEditor: jest.fn(), getDropProps: jest.fn(), onDrop: jest.fn(), createEmptyLayer: jest.fn(), @@ -71,6 +67,11 @@ export function createMockDatasource( getUsedDataViews: jest.fn(), onRefreshIndexPattern: jest.fn(), getDatasourceInfo: jest.fn(), + + DataPanelComponent: jest.fn().mockImplementation(() =>
), + LayerPanelComponent: jest.fn().mockImplementation(() =>
), + DimensionTriggerComponent: jest.fn().mockImplementation(() =>
), + DimensionEditorComponent: jest.fn().mockImplementation(() =>
), }; } diff --git a/x-pack/plugins/lens/public/mocks/store_mocks.tsx b/x-pack/plugins/lens/public/mocks/store_mocks.tsx index d4ba2d042b1ca..d6866438719f8 100644 --- a/x-pack/plugins/lens/public/mocks/store_mocks.tsx +++ b/x-pack/plugins/lens/public/mocks/store_mocks.tsx @@ -100,6 +100,7 @@ export const mountWithProvider = async ( wrappingComponent?: React.FC<{ children: React.ReactNode; }>; + wrappingComponentProps?: Record; attachTo?: HTMLElement; } ) => { @@ -120,6 +121,7 @@ export const getMountWithProviderParams = ( wrappingComponent?: React.FC<{ children: React.ReactNode; }>; + wrappingComponentProps?: Record; attachTo?: HTMLElement; } ) => { @@ -133,12 +135,13 @@ export const getMountWithProviderParams = ( attachTo?: HTMLElement | undefined; } = {}; if (options) { - const { wrappingComponent: _wrappingComponent, ...rest } = options; + const { wrappingComponent: _wrappingComponent, wrappingComponentProps, ...rest } = options; restOptions = rest; if (_wrappingComponent) { wrappingComponent = ({ children }) => { return _wrappingComponent({ + ...wrappingComponentProps, children: {children}, }); }; diff --git a/x-pack/plugins/lens/public/mocks/visualization_mock.ts b/x-pack/plugins/lens/public/mocks/visualization_mock.tsx similarity index 96% rename from x-pack/plugins/lens/public/mocks/visualization_mock.ts rename to x-pack/plugins/lens/public/mocks/visualization_mock.tsx index 8c519c59b0072..80f20e8c3af4e 100644 --- a/x-pack/plugins/lens/public/mocks/visualization_mock.ts +++ b/x-pack/plugins/lens/public/mocks/visualization_mock.tsx @@ -4,7 +4,7 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import React from 'react'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { Visualization, VisualizationMap } from '../types'; @@ -49,7 +49,7 @@ export function createMockVisualization(id = 'testVis'): jest.Mocked
), }; } diff --git a/x-pack/plugins/lens/public/native_renderer/index.ts b/x-pack/plugins/lens/public/native_renderer/index.ts deleted file mode 100644 index 61a92b7101d02..0000000000000 --- a/x-pack/plugins/lens/public/native_renderer/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * 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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -export * from './native_renderer'; diff --git a/x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx b/x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx deleted file mode 100644 index 8796f619277ff..0000000000000 --- a/x-pack/plugins/lens/public/native_renderer/native_renderer.test.tsx +++ /dev/null @@ -1,252 +0,0 @@ -/* - * 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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { useEffect } from 'react'; -import { render } from 'react-dom'; -import { NativeRenderer } from './native_renderer'; -import { act } from 'react-dom/test-utils'; - -function renderAndTriggerHooks(element: JSX.Element, mountpoint: Element) { - // act takes care of triggering state hooks - act(() => { - render(element, mountpoint); - }); -} - -describe('native_renderer', () => { - let mountpoint: Element; - - beforeEach(() => { - mountpoint = document.createElement('div'); - }); - - afterEach(() => { - mountpoint.remove(); - }); - - it('should render element in container', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - const containerElement = mountpoint.firstElementChild; - expect(renderSpy).toHaveBeenCalledWith(containerElement, testProps); - }); - - it('should render again if props change', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - renderAndTriggerHooks( - , - mountpoint - ); - renderAndTriggerHooks( - , - mountpoint - ); - expect(renderSpy).toHaveBeenCalledTimes(3); - const containerElement = mountpoint.firstElementChild; - expect(renderSpy).lastCalledWith(containerElement, { a: 'def' }); - }); - - it('should render again if props is just a string', () => { - const renderSpy = jest.fn(); - const testProps = 'abc'; - - renderAndTriggerHooks( - , - mountpoint - ); - renderAndTriggerHooks(, mountpoint); - renderAndTriggerHooks(, mountpoint); - expect(renderSpy).toHaveBeenCalledTimes(3); - const containerElement = mountpoint.firstElementChild; - expect(renderSpy).lastCalledWith(containerElement, 'def'); - }); - - it('should render again if props are extended', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - renderAndTriggerHooks( - , - mountpoint - ); - expect(renderSpy).toHaveBeenCalledTimes(2); - const containerElement = mountpoint.firstElementChild; - expect(renderSpy).lastCalledWith(containerElement, { a: 'abc', b: 'def' }); - }); - - it('should render again if props are limited', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc', b: 'def' }; - - renderAndTriggerHooks( - , - mountpoint - ); - renderAndTriggerHooks( - , - mountpoint - ); - expect(renderSpy).toHaveBeenCalledTimes(2); - const containerElement = mountpoint.firstElementChild; - expect(renderSpy).lastCalledWith(containerElement, { a: 'abc' }); - }); - - it('should render a div as container', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - const containerElement: Element = mountpoint.firstElementChild!; - expect(containerElement.nodeName).toBe('DIV'); - }); - - it('should pass regular html attributes to the wrapping element', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - const containerElement: HTMLElement = mountpoint.firstElementChild! as HTMLElement; - expect(containerElement.className).toBe('testClass'); - expect(containerElement.dataset.testSubj).toBe('container'); - }); - - it('should render a specified element as container', () => { - const renderSpy = jest.fn(); - const testProps = { a: 'abc' }; - - renderAndTriggerHooks( - , - mountpoint - ); - const containerElement: Element = mountpoint.firstElementChild!; - expect(containerElement.nodeName).toBe('SPAN'); - }); - - it('should properly unmount a react element that is mounted inside the renderer', () => { - let isUnmounted = false; - - function TestComponent() { - useEffect(() => { - return () => { - isUnmounted = true; - }; - }, []); - return <>Hello; - } - - renderAndTriggerHooks( - { - // This render function mimics the most common usage inside Lens - render(, element); - }} - nativeProps={{}} - />, - mountpoint - ); - - // Replaces the component at the mountpoint with nothing - renderAndTriggerHooks(<>Empty, mountpoint); - - expect(isUnmounted).toBe(true); - }); - - it('should call the unmount function provided for non-react elements', () => { - const unmountCallback = jest.fn(); - - renderAndTriggerHooks( - { - return unmountCallback; - }} - nativeProps={{}} - />, - mountpoint - ); - - // Replaces the component at the mountpoint with nothing - renderAndTriggerHooks(<>Empty, mountpoint); - - expect(unmountCallback).toHaveBeenCalled(); - }); - - it('should handle when the mount function is asynchronous without a cleanup fn', () => { - let isUnmounted = false; - - function TestComponent() { - useEffect(() => { - return () => { - isUnmounted = true; - }; - }, []); - return <>Hello; - } - - renderAndTriggerHooks( - { - render(, element); - }} - nativeProps={{}} - />, - mountpoint - ); - - // Replaces the component at the mountpoint with nothing - renderAndTriggerHooks(<>Empty, mountpoint); - - expect(isUnmounted).toBe(true); - }); - - it('should handle when the mount function is asynchronous with a cleanup fn', async () => { - const unmountCallback = jest.fn(); - - renderAndTriggerHooks( - { - return unmountCallback; - }} - nativeProps={{}} - />, - mountpoint - ); - - // Schedule a promise cycle to update the DOM - await new Promise((resolve) => setTimeout(resolve, 0)); - - // Replaces the component at the mountpoint with nothing - renderAndTriggerHooks(<>Empty, mountpoint); - - expect(unmountCallback).toHaveBeenCalled(); - }); -}); diff --git a/x-pack/plugins/lens/public/native_renderer/native_renderer.tsx b/x-pack/plugins/lens/public/native_renderer/native_renderer.tsx deleted file mode 100644 index f0659a130b293..0000000000000 --- a/x-pack/plugins/lens/public/native_renderer/native_renderer.tsx +++ /dev/null @@ -1,66 +0,0 @@ -/* - * 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; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import React, { HTMLAttributes, useEffect, useRef } from 'react'; -import { unmountComponentAtNode } from 'react-dom'; - -type CleanupCallback = (el: Element) => void; - -export interface NativeRendererProps extends HTMLAttributes { - render: ( - domElement: Element, - props: T - ) => Promise | CleanupCallback | void; - nativeProps: T; - tag?: string; -} - -/** - * A component which takes care of providing a mountpoint for a generic render - * function which takes an html element and an optional props object. - * By default the mountpoint element will be a div, this can be changed with the - * `tag` prop. - * - * If the rendered component tree was using React, we need to clean it up manually, - * otherwise the unmount event never happens. A future addition is for non-React components - * to get cleaned up, which could be added in the future. - * - * @param props - */ -export function NativeRenderer({ render, nativeProps, tag, ...rest }: NativeRendererProps) { - const elementRef = useRef(); - const cleanupRef = useRef<((cleanupElement: Element) => void) | void>(); - useEffect(() => { - return () => { - if (elementRef.current) { - if (cleanupRef.current && typeof cleanupRef.current === 'function') { - cleanupRef.current(elementRef.current); - } - unmountComponentAtNode(elementRef.current); - } - }; - }, []); - return React.createElement(tag || 'div', { - ...rest, - ref: (el) => { - if (el) { - elementRef.current = el; - // Handles the editor frame renderer, which is async - const result = render(el, nativeProps); - if (result instanceof Promise) { - result.then((cleanup) => { - if (typeof cleanup === 'function') { - cleanupRef.current = cleanup; - } - }); - } else if (typeof result === 'function') { - cleanupRef.current = result; - } - } - }, - }); -} diff --git a/x-pack/plugins/lens/public/types.ts b/x-pack/plugins/lens/public/types.ts index 042bdef118984..8ce305d967fe4 100644 --- a/x-pack/plugins/lens/public/types.ts +++ b/x-pack/plugins/lens/public/types.ts @@ -9,7 +9,7 @@ import type { IconType } from '@elastic/eui/src/components/icon/icon'; import type { CoreStart, SavedObjectReference, ResolvedSimpleSavedObject } from '@kbn/core/public'; import type { PaletteOutput } from '@kbn/coloring'; import type { TopNavMenuData } from '@kbn/navigation-plugin/public'; -import type { MutableRefObject } from 'react'; +import type { MutableRefObject, ReactElement } from 'react'; import type { Filter, TimeRange } from '@kbn/es-query'; import type { ExpressionAstExpression, @@ -40,12 +40,7 @@ import { estypes } from '@elastic/elasticsearch'; import React from 'react'; import { CellValueContext } from '@kbn/embeddable-plugin/public'; import { EventAnnotationGroupConfig } from '@kbn/event-annotation-plugin/common'; -import type { - DraggingIdentifier, - DragDropIdentifier, - DragContextValue, - DropType, -} from '@kbn/dom-drag-drop'; +import type { DraggingIdentifier, DragDropIdentifier, DropType } from '@kbn/dom-drag-drop'; import type { AccessorConfig } from '@kbn/visualization-ui-components/public'; import type { DateRange, LayerType, SortingHint } from '../common/types'; import type { @@ -372,26 +367,15 @@ export interface Datasource { }) => T; getSelectedFields?: (state: T) => string[]; - renderLayerSettings?: ( - domElement: Element, + LayerSettingsComponent?: ( props: DatasourceLayerSettingsProps - ) => ((cleanupElement: Element) => void) | void; - renderDataPanel: ( - domElement: Element, - props: DatasourceDataPanelProps - ) => ((cleanupElement: Element) => void) | void; - renderDimensionTrigger: ( - domElement: Element, - props: DatasourceDimensionTriggerProps - ) => ((cleanupElement: Element) => void) | void; - renderDimensionEditor: ( - domElement: Element, + ) => React.ReactElement> | null; + DataPanelComponent: (props: DatasourceDataPanelProps) => JSX.Element | null; + DimensionTriggerComponent: (props: DatasourceDimensionTriggerProps) => JSX.Element | null; + DimensionEditorComponent: ( props: DatasourceDimensionEditorProps - ) => ((cleanupElement: Element) => void) | void; - renderLayerPanel: ( - domElement: Element, - props: DatasourceLayerPanelProps - ) => ((cleanupElement: Element) => void) | void; + ) => ReactElement> | null; + LayerPanelComponent: (props: DatasourceLayerPanelProps) => JSX.Element | null; getDropProps: ( props: GetDropPropsArgs ) => { dropTypes: DropType[]; nextLabel?: string } | undefined; @@ -588,7 +572,6 @@ export interface DatasourceLayerSettingsProps { export interface DatasourceDataPanelProps { state: T; - dragDropContext: DragContextValue; setState: StateSetter; showNoDataPopover: () => void; core: Pick< @@ -1032,6 +1015,13 @@ export type RegisterLibraryAnnotationGroupFunction = (groupInfo: { id: string; group: EventAnnotationGroupConfig; }) => void; +interface AddLayerButtonProps { + supportedLayers: VisualizationLayerDescription[]; + addLayer: AddLayerFunction; + ensureIndexPattern: (specOrId: DataViewSpec | string) => Promise; + registerLibraryAnnotationGroup: RegisterLibraryAnnotationGroupFunction; +} + export interface Visualization { /** Plugin ID, such as "lnsXY" */ id: string; @@ -1161,27 +1151,24 @@ export interface Visualization - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Layer panel content rendered. This can be used to render a custom content below the title, * like a custom dataview switch */ - renderLayerPanel?: ( - domElement: Element, + LayerPanelComponent?: ( props: VisualizationLayerWidgetProps - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Toolbar rendered above the visualization. This is meant to be used to provide chart-level * settings for the visualization. */ - renderToolbar?: ( - domElement: Element, + ToolbarComponent?: ( props: VisualizationToolbarProps - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * The frame is telling the visualization to update or set a dimension based on user interaction @@ -1216,49 +1203,42 @@ export interface Visualization) => Record<'data' | 'appearance', boolean>; - renderLayerSettings?: ( - domElement: Element, + LayerSettingsComponent?: ( props: VisualizationLayerSettingsProps & { section: 'data' | 'appearance' } - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Additional editor that gets rendered inside the dimension popover in the "appearance" section. * This can be used to configure dimension-specific options */ - renderDimensionEditor?: ( - domElement: Element, + DimensionEditorComponent?: ( props: VisualizationDimensionEditorProps - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Additional editor that gets rendered inside the dimension popover in an additional section below "appearance". * This can be used to configure dimension-specific options */ - renderDimensionEditorAdditionalSection?: ( - domElement: Element, + DimensionEditorAdditionalSectionComponent?: ( props: VisualizationDimensionEditorProps - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Additional editor that gets rendered inside the data section. * This can be used to configure dimension-specific options */ - renderDimensionEditorDataExtra?: ( - domElement: Element, + DimensionEditorDataExtraComponent?: ( props: VisualizationDimensionEditorProps - ) => ((cleanupElement: Element) => void) | void; + ) => null | ReactElement>; /** * Renders dimension trigger. Used only for noDatasource layers */ - renderDimensionTrigger?: (props: { + DimensionTriggerComponent?: (props: { columnId: string; label: string; hideTooltip?: boolean; - }) => JSX.Element | null; - getAddLayerButtonComponent?: (props: { - supportedLayers: VisualizationLayerDescription[]; - addLayer: AddLayerFunction; - ensureIndexPattern: (specOrId: DataViewSpec | string) => Promise; - registerLibraryAnnotationGroup: RegisterLibraryAnnotationGroupFunction; - }) => JSX.Element | null; + }) => null | ReactElement<{ columnId: string; label: string; hideTooltip?: boolean }>; + getAddLayerButtonComponent?: ( + props: AddLayerButtonProps + ) => null | ReactElement; /** * Creates map of columns ids and unique lables. Used only for noDatasource layers */ diff --git a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx index ecc6bc958124f..35757771af754 100644 --- a/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/datatable/visualization.tsx @@ -6,13 +6,10 @@ */ import React from 'react'; -import { render } from 'react-dom'; import { Ast } from '@kbn/interpreter'; -import { I18nProvider } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import { PaletteRegistry, CUSTOM_PALETTE } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartDatatable } from '@kbn/chart-icons'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; @@ -337,37 +334,16 @@ export const getDatatableVisualization = ({ sorting: prevState.sorting?.columnId === columnId ? undefined : prevState.sorting, }; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, - renderDimensionEditorAdditionalSection(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorAdditionalSectionComponent(props) { + return ; }, - renderDimensionEditorDataExtra(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorDataExtraComponent(props) { + return ; }, getSupportedLayers() { @@ -522,15 +498,8 @@ export const getDatatableVisualization = ({ }, []); }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, onEditAction(state, event) { diff --git a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx index ddab89444419f..b943e9601f24b 100644 --- a/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/gauge/visualization.tsx @@ -6,11 +6,9 @@ */ import React from 'react'; -import { render } from 'react-dom'; import { i18n } from '@kbn/i18n'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n-react'; +import { FormattedMessage } from '@kbn/i18n-react'; import { Ast } from '@kbn/interpreter'; import { buildExpressionFunction, DatatableRow } from '@kbn/expressions-plugin/common'; import { PaletteRegistry, CustomPaletteParams, CUSTOM_PALETTE } from '@kbn/coloring'; @@ -400,26 +398,12 @@ export const getGaugeVisualization = ({ return update; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, getSupportedLayers(state, frame) { diff --git a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx index 7d448e56e9fee..654d69284718c 100644 --- a/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/heatmap/visualization.tsx @@ -6,15 +6,13 @@ */ import React from 'react'; -import { render } from 'react-dom'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n-react'; +import { FormattedMessage } from '@kbn/i18n-react'; import { Ast } from '@kbn/interpreter'; import { Position } from '@elastic/charts'; import { IconChartHeatmap } from '@kbn/chart-icons'; import { CUSTOM_PALETTE, PaletteRegistry, CustomPaletteParams } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; import { HeatmapConfiguration } from '@kbn/visualizations-plugin/common'; @@ -272,26 +270,12 @@ export const getHeatmapVisualization = ({ return update; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, getSupportedLayers() { diff --git a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx index 85fea42623fc4..2f164ba3ed5b0 100644 --- a/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/legacy_metric/visualization.tsx @@ -5,13 +5,10 @@ * 2.0. */ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; import { euiThemeVars } from '@kbn/ui-theme'; -import { render } from 'react-dom'; import { Ast } from '@kbn/interpreter'; import { PaletteOutput, PaletteRegistry, CUSTOM_PALETTE, shiftPalette } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { ColorMode, CustomPaletteState } from '@kbn/charts-plugin/common'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { IconChartMetric } from '@kbn/chart-icons'; @@ -290,26 +287,12 @@ export const getLegacyMetricVisualization = ({ return { ...prevState, accessor: undefined, colorMode: ColorMode.None, palette: undefined }; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, getVisualizationInfo(state: LegacyMetricState) { diff --git a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx index 4f18899a118df..b003174232125 100644 --- a/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/metric/visualization.tsx @@ -7,14 +7,11 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; -import { render } from 'react-dom'; import { PaletteOutput, PaletteRegistry, CustomPaletteParams } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { LayoutDirection } from '@elastic/charts'; import { euiLightVars, euiThemeVars } from '@kbn/ui-theme'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { IconChartMetric } from '@kbn/chart-icons'; import { AccessorConfig } from '@kbn/visualization-ui-components/public'; import { CollapseFunction } from '../../../common/expressions'; @@ -592,37 +589,16 @@ export const getMetricVisualization = ({ return updated; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, - renderDimensionEditorAdditionalSection(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorAdditionalSectionComponent(props) { + return ; }, getDisplayOptions() { diff --git a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx index da4f275b49539..444342f08b723 100644 --- a/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/partition/visualization.tsx @@ -6,12 +6,10 @@ */ import React from 'react'; -import { render } from 'react-dom'; import { i18n } from '@kbn/i18n'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n-react'; +import { FormattedMessage } from '@kbn/i18n-react'; import type { PaletteRegistry } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import { EuiSpacer } from '@elastic/eui'; import { PartitionVisConfiguration } from '@kbn/visualizations-plugin/common/convert_to_lens'; @@ -459,25 +457,11 @@ export const getPieVisualization = ({ layers: newState.layers.map((l) => (l.layerId === layerId ? newLayer : l)), }; }, - renderDimensionEditor(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorComponent(props) { + return ; }, - renderDimensionEditorDataExtra(domElement, props) { - render( - - - - - , - domElement - ); + DimensionEditorDataExtraComponent(props) { + return ; }, getSupportedLayers() { @@ -501,30 +485,16 @@ export const getPieVisualization = ({ toPreviewExpression: (state, layers, datasourceExpressionsByLayers) => toPreviewExpression(state, layers, paletteService, datasourceExpressionsByLayers), - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, hasLayerSettings(props) { return { data: props.state.shape !== PieChartTypes.MOSAIC, appearance: false }; }, - renderLayerSettings(domElement, props) { - render( - - - - - , - domElement - ); + LayerSettingsComponent(props) { + return ; }, getSuggestionFromConvertToLensContext(props) { diff --git a/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx b/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx index 09e988b445795..d1bd1ec337bc0 100644 --- a/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/tagcloud/tagcloud_visualization.tsx @@ -7,10 +7,7 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; -import { render } from 'react-dom'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import type { ExpressionTagcloudFunctionDefinition } from '@kbn/expression-tagcloud-plugin/common'; import { LayerTypes } from '@kbn/expression-xy-plugin/public'; @@ -268,31 +265,20 @@ export const getTagcloudVisualization = ({ return update; }, - renderDimensionEditor(domElement, props) { + DimensionEditorComponent(props) { if (props.groupId === TAG_GROUP_ID) { - render( - - - - - , - domElement + return ( + ); } + return null; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, }); diff --git a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx index 7d47cf9602415..d9f48f7b4d41b 100644 --- a/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx +++ b/x-pack/plugins/lens/public/visualizations/xy/visualization.tsx @@ -6,9 +6,8 @@ */ import React from 'react'; -import { render } from 'react-dom'; import { Position } from '@elastic/charts'; -import { FormattedMessage, I18nProvider } from '@kbn/i18n-react'; +import { FormattedMessage } from '@kbn/i18n-react'; import { i18n } from '@kbn/i18n'; import type { PaletteRegistry } from '@kbn/coloring'; import { IconChartBarReferenceLine, IconChartBarAnnotations } from '@kbn/chart-icons'; @@ -18,7 +17,6 @@ import { EventAnnotationServiceType, getAnnotationAccessor, } from '@kbn/event-annotation-plugin/public'; -import { KibanaContextProvider, KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public'; import type { DataPublicPluginStart } from '@kbn/data-plugin/public'; import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public'; @@ -340,15 +338,8 @@ export const getXyVisualization = ({ return { data: Boolean(layer && isAnnotationsLayer(layer)), appearance: false }; }, - renderLayerSettings(domElement, props) { - render( - - - - - , - domElement - ); + LayerSettingsComponent(props) { + return ; }, onIndexPatternChange(state, indexPatternId, layerId) { const layerIndex = state.layers.findIndex((l) => l.layerId === layerId); @@ -622,61 +613,29 @@ export const getXyVisualization = ({ }; }, - renderLayerPanel(domElement, props) { + LayerPanelComponent(props) { const { onChangeIndexPattern, ...otherProps } = props; - render( - - - - { - // TODO: should it trigger an action as in the datasource? - onChangeIndexPattern(indexPatternId); - }} - /> - - - , - domElement + + return ( + { + // TODO: should it trigger an action as in the datasource? + onChangeIndexPattern(indexPatternId); + }} + /> ); }, - renderLayerHeader(domElement, props) { - render( - - - - - , - domElement - ); + LayerHeaderComponent(props) { + return ; }, - renderToolbar(domElement, props) { - render( - - - - - , - domElement - ); + ToolbarComponent(props) { + return ; }, - renderDimensionEditor(domElement, props) { + DimensionEditorComponent(props) { const allProps = { ...props, datatableUtilities: data.datatableUtilities, @@ -692,31 +651,10 @@ export const getXyVisualization = ({ ); - render( - - - - {dimensionEditor} - - - , - domElement - ); + return dimensionEditor; }, - renderDimensionEditorDataExtra(domElement, props) { + DimensionEditorDataExtraComponent(props) { const allProps = { ...props, datatableUtilities: data.datatableUtilities, @@ -725,34 +663,13 @@ export const getXyVisualization = ({ }; const layer = props.state.layers.find((l) => l.layerId === props.layerId)!; if (isReferenceLayer(layer)) { - return; + return null; } if (isAnnotationsLayer(layer)) { - return; + return null; } - render( - - - - - - - , - domElement - ); + return ; }, getAddLayerButtonComponent: (props) => { return ( @@ -986,7 +903,7 @@ export const getXyVisualization = ({ state?.layers.filter(isAnnotationsLayer).map(({ indexPatternId }) => indexPatternId) ?? [] ); }, - renderDimensionTrigger({ columnId, label }) { + DimensionTriggerComponent({ columnId, label }) { if (label) { return ; } diff --git a/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx b/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx index 5018863acbc8d..0d22be959ef2a 100644 --- a/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx +++ b/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx @@ -195,20 +195,16 @@ export const getVisualization = ({ return update; }, - renderDimensionEditor(domElement, props) { + DimensionEditorComponent(props) { if (props.groupId === REGION_KEY_GROUP_ID) { - render( - - - - - , - domElement + return ( + ); } + return null; }, }); From 74bc45d403a105a5a97ee50b362dc898a3cac623 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:10:55 +0000 Subject: [PATCH 2/3] [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix' --- .../third_party_vis_lens_example/public/visualization.tsx | 2 -- .../maps/public/lens/choropleth_chart/visualization.tsx | 3 --- 2 files changed, 5 deletions(-) diff --git a/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx b/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx index e66117cb83bc9..60b45bad9c423 100644 --- a/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx +++ b/x-pack/examples/third_party_vis_lens_example/public/visualization.tsx @@ -7,10 +7,8 @@ import React from 'react'; import { EuiFormRow, EuiColorPicker } from '@elastic/eui'; -import { render } from 'react-dom'; import { Ast } from '@kbn/interpreter'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { Visualization, OperationMetadata } from '@kbn/lens-plugin/public'; import { layerTypes } from '@kbn/lens-plugin/public'; import type { RotatingNumberState } from '../common/types'; diff --git a/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx b/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx index 0d22be959ef2a..81536846faf2c 100644 --- a/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx +++ b/x-pack/plugins/maps/public/lens/choropleth_chart/visualization.tsx @@ -7,12 +7,9 @@ import React from 'react'; import { i18n } from '@kbn/i18n'; -import { I18nProvider } from '@kbn/i18n-react'; -import { render } from 'react-dom'; import type { FileLayer } from '@elastic/ems-client'; import type { PaletteRegistry } from '@kbn/coloring'; import { ThemeServiceStart } from '@kbn/core/public'; -import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public'; import { layerTypes } from '@kbn/lens-plugin/public'; import type { OperationMetadata, SuggestionRequest, Visualization } from '@kbn/lens-plugin/public'; import { IconRegionMap } from '@kbn/chart-icons'; From 189b6e6fbc61c001e7d1874333b10204ffef0922 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 11 Jul 2023 10:17:14 +0000 Subject: [PATCH 3/3] [CI] Auto-commit changed files from 'node scripts/lint_ts_projects --fix' --- x-pack/examples/third_party_vis_lens_example/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/examples/third_party_vis_lens_example/tsconfig.json b/x-pack/examples/third_party_vis_lens_example/tsconfig.json index ef98a7a9f4479..50b96685bd3d8 100644 --- a/x-pack/examples/third_party_vis_lens_example/tsconfig.json +++ b/x-pack/examples/third_party_vis_lens_example/tsconfig.json @@ -16,7 +16,6 @@ "kbn_references": [ "@kbn/core", "@kbn/expressions-plugin", - "@kbn/kibana-react-plugin", "@kbn/data-views-plugin", "@kbn/field-formats-plugin", "@kbn/lens-plugin",