From 3ad861e4b1bdd53376775746b4b91e88a96a76d5 Mon Sep 17 00:00:00 2001 From: Nathan Reese Date: Thu, 15 Aug 2024 09:59:10 -0600 Subject: [PATCH] [control group] implement lastUsedDataViewId$ (#190269) PR added `lastUsedDataViewId$` to `ControlGroupApi`. `lastUsedDataViewId$` is implemented in `initializeControlsManager`. PR also cleaned up typings by removing `DataControlEditorState`. `DataControlEditorState` was a weird smooshing together of DefaultDataControlState and stuff used by the editor. Instead of `DataControlEditorState`, values used by the editor are just passed in as top level keys. --------- Co-authored-by: Elastic Machine --- .../react_control_example.tsx | 1 - .../get_control_group_factory.tsx | 9 +- .../init_controls_manager.test.ts | 106 +++++++++++++----- .../control_group/init_controls_manager.ts | 38 ++++++- .../react_controls/control_group/types.ts | 1 + .../data_control_editor.test.tsx | 31 +++-- .../data_controls/data_control_editor.tsx | 48 ++++---- .../data_controls/initialize_data_control.ts | 16 +-- .../open_data_control_editor.tsx | 26 +++-- .../options_list_editor_options.test.tsx | 26 ++--- .../options_list_editor_options.tsx | 6 +- .../get_range_slider_control_factory.test.tsx | 4 +- .../controls/data_controls/types.ts | 4 +- 13 files changed, 211 insertions(+), 105 deletions(-) diff --git a/examples/controls_example/public/app/react_control_example/react_control_example.tsx b/examples/controls_example/public/app/react_control_example/react_control_example.tsx index 700b899805be89..4ed6703c46c842 100644 --- a/examples/controls_example/public/app/react_control_example/react_control_example.tsx +++ b/examples/controls_example/public/app/react_control_example/react_control_example.tsx @@ -139,7 +139,6 @@ export const ReactControlExample = ({ addNewPanel: () => { return Promise.resolve(undefined); }, - lastUsedDataViewId: new BehaviorSubject(WEB_LOGS_DATA_VIEW_ID), saveNotification$, reload$, }; diff --git a/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx b/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx index 00a1978bb2679b..ee241dcfea0fc7 100644 --- a/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx +++ b/src/plugins/controls/public/react_controls/control_group/get_control_group_factory.tsx @@ -73,7 +73,13 @@ export const getControlGroupEmbeddableFactory = (services: { } = initialRuntimeState; const autoApplySelections$ = new BehaviorSubject(autoApplySelections); - const controlsManager = initControlsManager(initialChildControlState); + const parentDataViewId = apiPublishesDataViews(parentApi) + ? parentApi.dataViews.value?.[0]?.id + : undefined; + const controlsManager = initControlsManager( + initialChildControlState, + parentDataViewId ?? (await services.dataViews.getDefaultId()) + ); const selectionsManager = initSelectionsManager({ ...controlsManager.api, autoApplySelections$, @@ -172,6 +178,7 @@ export const getControlGroupEmbeddableFactory = (services: { initialState: { grow: api.grow.getValue(), width: api.width.getValue(), + dataViewId: controlsManager.api.lastUsedDataViewId$.value, }, onSave: ({ type: controlType, state: initialState }) => { api.addNewPanel({ diff --git a/src/plugins/controls/public/react_controls/control_group/init_controls_manager.test.ts b/src/plugins/controls/public/react_controls/control_group/init_controls_manager.test.ts index 451681fe5b3fde..76899c3d9d0b4a 100644 --- a/src/plugins/controls/public/react_controls/control_group/init_controls_manager.test.ts +++ b/src/plugins/controls/public/react_controls/control_group/init_controls_manager.test.ts @@ -7,19 +7,24 @@ */ import { DefaultControlApi } from '../controls/types'; -import { initControlsManager } from './init_controls_manager'; +import { initControlsManager, getLastUsedDataViewId } from './init_controls_manager'; jest.mock('uuid', () => ({ v4: jest.fn().mockReturnValue('delta'), })); +const DEFAULT_DATA_VIEW_ID = 'myDataView'; + describe('PresentationContainer api', () => { test('addNewPanel should add control at end of controls', async () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 0 }, - bravo: { type: 'testControl', order: 1 }, - charlie: { type: 'testControl', order: 2 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 0 }, + bravo: { type: 'testControl', order: 1 }, + charlie: { type: 'testControl', order: 2 }, + }, + DEFAULT_DATA_VIEW_ID + ); const addNewPanelPromise = controlsManager.api.addNewPanel({ panelType: 'testControl', initialState: {}, @@ -35,11 +40,14 @@ describe('PresentationContainer api', () => { }); test('removePanel should remove control', () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 0 }, - bravo: { type: 'testControl', order: 1 }, - charlie: { type: 'testControl', order: 2 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 0 }, + bravo: { type: 'testControl', order: 1 }, + charlie: { type: 'testControl', order: 2 }, + }, + DEFAULT_DATA_VIEW_ID + ); controlsManager.api.removePanel('bravo'); expect(controlsManager.controlsInOrder$.value.map((element) => element.id)).toEqual([ 'alpha', @@ -48,11 +56,14 @@ describe('PresentationContainer api', () => { }); test('replacePanel should replace control', async () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 0 }, - bravo: { type: 'testControl', order: 1 }, - charlie: { type: 'testControl', order: 2 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 0 }, + bravo: { type: 'testControl', order: 1 }, + charlie: { type: 'testControl', order: 2 }, + }, + DEFAULT_DATA_VIEW_ID + ); const replacePanelPromise = controlsManager.api.replacePanel('bravo', { panelType: 'testControl', initialState: {}, @@ -68,10 +79,13 @@ describe('PresentationContainer api', () => { describe('untilInitialized', () => { test('should not resolve until all controls are initialized', async () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 0 }, - bravo: { type: 'testControl', order: 1 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 0 }, + bravo: { type: 'testControl', order: 1 }, + }, + DEFAULT_DATA_VIEW_ID + ); let isDone = false; controlsManager.api.untilInitialized().then(() => { isDone = true; @@ -89,10 +103,13 @@ describe('PresentationContainer api', () => { }); test('should resolve when all control already initialized ', async () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 0 }, - bravo: { type: 'testControl', order: 1 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 0 }, + bravo: { type: 'testControl', order: 1 }, + }, + DEFAULT_DATA_VIEW_ID + ); controlsManager.setControlApi('alpha', {} as unknown as DefaultControlApi); controlsManager.setControlApi('bravo', {} as unknown as DefaultControlApi); @@ -109,10 +126,13 @@ describe('PresentationContainer api', () => { describe('snapshotControlsRuntimeState', () => { test('should snapshot runtime state for all controls', async () => { - const controlsManager = initControlsManager({ - alpha: { type: 'testControl', order: 1 }, - bravo: { type: 'testControl', order: 0 }, - }); + const controlsManager = initControlsManager( + { + alpha: { type: 'testControl', order: 1 }, + bravo: { type: 'testControl', order: 0 }, + }, + DEFAULT_DATA_VIEW_ID + ); controlsManager.setControlApi('alpha', { snapshotRuntimeState: () => { return { key1: 'alpha value' }; @@ -137,3 +157,33 @@ describe('snapshotControlsRuntimeState', () => { }); }); }); + +describe('getLastUsedDataViewId', () => { + test('should return last used data view id', () => { + const dataViewId = getLastUsedDataViewId( + [ + { id: 'alpha', type: 'testControl' }, + { id: 'bravo', type: 'testControl' }, + { id: 'charlie', type: 'testControl' }, + ], + { + alpha: { dataViewId: '1', type: 'testControl', order: 0 }, + bravo: { dataViewId: '2', type: 'testControl', order: 1 }, + charlie: { type: 'testControl', order: 2 }, + } + ); + expect(dataViewId).toBe('2'); + }); + + test('should return undefined when there are no controls', () => { + const dataViewId = getLastUsedDataViewId([], {}); + expect(dataViewId).toBeUndefined(); + }); + + test('should return undefined when there are no controls with data views', () => { + const dataViewId = getLastUsedDataViewId([{ id: 'alpha', type: 'testControl' }], { + alpha: { type: 'testControl', order: 0 }, + }); + expect(dataViewId).toBeUndefined(); + }); +}); diff --git a/src/plugins/controls/public/react_controls/control_group/init_controls_manager.ts b/src/plugins/controls/public/react_controls/control_group/init_controls_manager.ts index d9eccfa126a8a8..0e762bfd53fa31 100644 --- a/src/plugins/controls/public/react_controls/control_group/init_controls_manager.ts +++ b/src/plugins/controls/public/react_controls/control_group/init_controls_manager.ts @@ -18,9 +18,10 @@ import { BehaviorSubject, first, merge } from 'rxjs'; import { PublishingSubject, StateComparators } from '@kbn/presentation-publishing'; import { omit } from 'lodash'; import { apiHasSnapshottableState } from '@kbn/presentation-containers/interfaces/serialized_state'; -import { ControlPanelsState, ControlPanelState } from './types'; +import { ControlGroupApi, ControlPanelsState, ControlPanelState } from './types'; import { DefaultControlApi, DefaultControlState } from '../controls/types'; import { ControlGroupComparatorState } from './control_group_unsaved_changes_api'; +import { DefaultDataControlState } from '../controls/data_controls/types'; export type ControlsInOrder = Array<{ id: string; type: string }>; @@ -35,7 +36,10 @@ export function getControlsInOrder(initialControlPanelsState: ControlPanelsState .map(({ id, type }) => ({ id, type })); // filter out `order` } -export function initControlsManager(initialControlPanelsState: ControlPanelsState) { +export function initControlsManager( + initialControlPanelsState: ControlPanelsState, + defaultDataViewId: string | null +) { const lastSavedControlsPanelState$ = new BehaviorSubject(initialControlPanelsState); const initialControlIds = Object.keys(initialControlPanelsState); const children$ = new BehaviorSubject<{ [key: string]: DefaultControlApi }>({}); @@ -45,6 +49,11 @@ export function initControlsManager(initialControlPanelsState: ControlPanelsStat const controlsInOrder$ = new BehaviorSubject( getControlsInOrder(initialControlPanelsState) ); + const lastUsedDataViewId$ = new BehaviorSubject( + getLastUsedDataViewId(controlsInOrder$.value, initialControlPanelsState) ?? + defaultDataViewId ?? + undefined + ); function untilControlLoaded( id: string @@ -79,6 +88,9 @@ export function initControlsManager(initialControlPanelsState: ControlPanelsStat { panelType, initialState }: PanelPackage, index: number ) { + if ((initialState as DefaultDataControlState)?.dataViewId) { + lastUsedDataViewId$.next((initialState as DefaultDataControlState).dataViewId); + } const id = generateId(); const nextControlsInOrder = [...controlsInOrder$.value]; nextControlsInOrder.splice(index, 0, { @@ -156,6 +168,7 @@ export function initControlsManager(initialControlPanelsState: ControlPanelsStat return controlsRuntimeState; }, api: { + lastUsedDataViewId$: lastUsedDataViewId$ as PublishingSubject, getSerializedStateForChild: (childId: string) => { const controlPanelState = controlsPanelState[childId]; return controlPanelState ? { rawState: controlPanelState } : undefined; @@ -196,7 +209,8 @@ export function initControlsManager(initialControlPanelsState: ControlPanelsStat }); }, } as PresentationContainer & - HasSerializedChildState & { untilInitialized: () => Promise }, + HasSerializedChildState & + Pick, comparators: { controlsInOrder: [ controlsInOrder$, @@ -222,3 +236,21 @@ export function initControlsManager(initialControlPanelsState: ControlPanelsStat >, }; } + +export function getLastUsedDataViewId( + controlsInOrder: ControlsInOrder, + initialControlPanelsState: ControlPanelsState< + ControlPanelState & Partial + > +) { + let dataViewId: string | undefined; + for (let i = controlsInOrder.length - 1; i >= 0; i--) { + const controlId = controlsInOrder[i].id; + const controlState = initialControlPanelsState[controlId]; + if (controlState?.dataViewId) { + dataViewId = controlState.dataViewId; + break; + } + } + return dataViewId; +} diff --git a/src/plugins/controls/public/react_controls/control_group/types.ts b/src/plugins/controls/public/react_controls/control_group/types.ts index 0ff6e31faeee65..f00aaeae578b40 100644 --- a/src/plugins/controls/public/react_controls/control_group/types.ts +++ b/src/plugins/controls/public/react_controls/control_group/types.ts @@ -73,6 +73,7 @@ export type ControlGroupApi = PresentationContainer & openAddDataControlFlyout: (settings?: { controlInputTransform?: ControlInputTransform; }) => void; + lastUsedDataViewId$: PublishingSubject; }; export interface ControlGroupRuntimeState { diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.test.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.test.tsx index 9b5798efdc2209..58715f6b2305e8 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.test.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.test.tsx @@ -25,7 +25,6 @@ jest.mock('../../control_factory_registry', () => ({ import { DEFAULT_CONTROL_GROW, DEFAULT_CONTROL_WIDTH } from '../../../../common'; import { ControlGroupApi } from '../../control_group/types'; import { DataControlEditor } from './data_control_editor'; -import { DataControlEditorState } from './open_data_control_editor'; import { getMockedOptionsListControlFactory, getMockedRangeSliderControlFactory, @@ -57,7 +56,6 @@ mockDataViews.get = jest.fn().mockResolvedValue(mockDataView); const dashboardApi = { timeRange$: new BehaviorSubject(undefined), - lastUsedDataViewId$: new BehaviorSubject(mockDataView.id!), }; const controlGroupApi = { parentApi: dashboardApi, @@ -68,8 +66,14 @@ const controlGroupApi = { describe('Data control editor', () => { const mountComponent = async ({ initialState, + controlId, + controlType, + initialDefaultPanelTitle, }: { - initialState?: Partial; + initialState?: Partial; + controlId?: string; + controlType?: string; + initialDefaultPanelTitle?: string; }) => { mockDataViews.get = jest.fn().mockResolvedValue(mockDataView); @@ -78,11 +82,14 @@ describe('Data control editor', () => { {}} onSave={() => {}} - parentApi={controlGroupApi} + controlGroupApi={controlGroupApi} initialState={{ - dataViewId: dashboardApi.lastUsedDataViewId$.getValue(), + dataViewId: mockDataView.id, ...initialState, }} + controlId={controlId} + controlType={controlType} + initialDefaultPanelTitle={initialDefaultPanelTitle} services={{ dataViews: mockDataViews }} /> @@ -238,11 +245,11 @@ describe('Data control editor', () => { test('auto-fills input with the default title', async () => { const controlEditor = await mountComponent({ initialState: { - controlType: 'optionsList', - controlId: 'testId', fieldName: 'machine.os.raw', - defaultPanelTitle: 'OS', }, + controlType: 'optionsList', + controlId: 'testId', + initialDefaultPanelTitle: 'OS', }); const titleInput = await controlEditor.findByTestId('control-editor-title-input'); expect(titleInput.getAttribute('value')).toBe('OS'); @@ -252,11 +259,11 @@ describe('Data control editor', () => { test('auto-fills input with the custom title', async () => { const controlEditor = await mountComponent({ initialState: { - controlType: 'optionsList', - controlId: 'testId', fieldName: 'machine.os.raw', title: 'Custom title', }, + controlType: 'optionsList', + controlId: 'testId', }); const titleInput = await controlEditor.findByTestId('control-editor-title-input'); expect(titleInput.getAttribute('value')).toBe('Custom title'); @@ -267,10 +274,10 @@ describe('Data control editor', () => { test('selects the provided control type', async () => { const controlEditor = await mountComponent({ initialState: { - controlType: 'rangeSlider', - controlId: 'testId', fieldName: 'bytes', }, + controlType: 'rangeSlider', + controlId: 'testId', }); expect(controlEditor.getByTestId('create__optionsList')).toBeEnabled(); diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.tsx index 701d8c1d85391b..a39b0ea03b4229 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/data_control_editor.tsx @@ -46,14 +46,18 @@ import { getAllControlTypes, getControlFactory } from '../../control_factory_reg import { ControlGroupApi } from '../../control_group/types'; import { DataControlEditorStrings } from './data_control_constants'; import { getDataControlFieldRegistry } from './data_control_editor_utils'; -import { DataControlEditorState } from './open_data_control_editor'; import { DataControlFactory, DefaultDataControlState, isDataControlFactory } from './types'; -export interface ControlEditorProps { - initialState: State; - parentApi: ControlGroupApi; // controls must always have a parent API - onCancel: (newState: State) => void; - onSave: (newState: State, type: string) => void; +export interface ControlEditorProps< + State extends DefaultDataControlState = DefaultDataControlState +> { + initialState: Partial; + controlType?: string; + controlId?: string; + initialDefaultPanelTitle?: string; + controlGroupApi: ControlGroupApi; // controls must always have a parent API + onCancel: (newState: Partial) => void; + onSave: (newState: Partial, type: string) => void; services: { dataViews: DataViewsPublicPluginStart; }; @@ -130,27 +134,27 @@ const CompatibleControlTypesComponent = ({ ); }; -export const DataControlEditor = ({ +export const DataControlEditor = ({ initialState, + controlId, + controlType, + initialDefaultPanelTitle, onSave, onCancel, - parentApi: controlGroup, + controlGroupApi, /** TODO: These should not be props */ services: { dataViews: dataViewService }, }: ControlEditorProps) => { const [defaultGrow, defaultWidth] = useBatchedPublishingSubjects( - controlGroup.grow, - controlGroup.width - // controlGroup.parentApi?.lastUsedDataViewId, // TODO: Make this work + controlGroupApi.grow, + controlGroupApi.width ); - const [editorState, setEditorState] = useState(initialState); + const [editorState, setEditorState] = useState>(initialState); const [defaultPanelTitle, setDefaultPanelTitle] = useState( - initialState.defaultPanelTitle ?? initialState.fieldName ?? '' + initialDefaultPanelTitle ?? initialState.fieldName ?? '' ); const [panelTitle, setPanelTitle] = useState(initialState.title ?? defaultPanelTitle); - const [selectedControlType, setSelectedControlType] = useState( - initialState.controlType - ); + const [selectedControlType, setSelectedControlType] = useState(controlType); const [controlOptionsValid, setControlOptionsValid] = useState(true); /** TODO: Make `editorConfig` work when refactoring the `ControlGroupRenderer` */ @@ -209,22 +213,22 @@ export const DataControlEditor = setEditorState({ ...editorState, ...newState })} setControlEditorValid={setControlOptionsValid} - parentApi={controlGroup} + controlGroupApi={controlGroupApi} /> ); - }, [fieldRegistry, selectedControlType, initialState, editorState, controlGroup]); + }, [fieldRegistry, selectedControlType, initialState, editorState, controlGroupApi]); return ( <>

- {!initialState.controlId // if no ID, then we are creating a new control + {!controlId // if no ID, then we are creating a new control ? DataControlEditorStrings.manageControl.getFlyoutCreateTitle() : DataControlEditorStrings.manageControl.getFlyoutEditTitle()}

@@ -385,7 +389,7 @@ export const DataControlEditor = {CustomSettingsComponent} - {initialState.controlId && ( + {controlId && ( <> { onCancel(initialState); // don't want to show "lost changes" warning - controlGroup.removePanel(initialState.controlId!); + controlGroupApi.removePanel(controlId!); }} > {DataControlEditorStrings.manageControl.getDeleteButtonTitle()} diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/initialize_data_control.ts b/src/plugins/controls/public/react_controls/controls/data_controls/initialize_data_control.ts index 12bfba658c9f5a..312701dd22c320 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/initialize_data_control.ts +++ b/src/plugins/controls/public/react_controls/controls/data_controls/initialize_data_control.ts @@ -36,7 +36,7 @@ export const initializeDataControl = ( * responsible for managing */ editorStateManager: ControlStateManager, - controlGroup: ControlGroupApi, + controlGroupApi: ControlGroupApi, services: { core: CoreStart; dataViews: DataViewsPublicPluginStart; @@ -159,22 +159,24 @@ export const initializeDataControl = ( (Object.keys(initialState) as Array).forEach( (key) => { if (!isEqual(mergedStateManager[key].getValue(), newState[key])) { - mergedStateManager[key].next(newState[key]); + mergedStateManager[key].next( + newState[key] as DefaultDataControlState & EditorState[typeof key] + ); } } ); } else { // replace the control with a new one of the updated type - controlGroup.replacePanel(controlId, { panelType: newType, initialState: newState }); + controlGroupApi.replacePanel(controlId, { panelType: newType, initialState: newState }); } }, initialState: { ...initialState, - controlType, - controlId, - defaultPanelTitle: defaultPanelTitle.getValue(), }, - controlGroupApi: controlGroup, + controlType, + controlId, + initialDefaultPanelTitle: defaultPanelTitle.getValue(), + controlGroupApi, }); }; diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/open_data_control_editor.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/open_data_control_editor.tsx index fbddf0e7af8311..4aadfbb78deffd 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/open_data_control_editor.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/open_data_control_editor.tsx @@ -20,23 +20,22 @@ import { ControlGroupApi } from '../../control_group/types'; import { DataControlEditor } from './data_control_editor'; import { DefaultDataControlState } from './types'; -export type DataControlEditorState = Partial & { - fieldName?: string; - controlType?: string; - controlId?: string; - defaultPanelTitle?: string; -}; - export const openDataControlEditor = < - State extends DataControlEditorState = DataControlEditorState + State extends DefaultDataControlState = DefaultDataControlState >({ initialState, + controlType, + controlId, + initialDefaultPanelTitle, onSave, controlGroupApi, services, }: { - initialState: State; - onSave: ({ type, state }: { type: string; state: State }) => void; + initialState: Partial; + controlType?: string; + controlId?: string; + initialDefaultPanelTitle?: string; + onSave: ({ type, state }: { type: string; state: Partial }) => void; controlGroupApi: ControlGroupApi; services: { core: CoreStart; @@ -50,7 +49,7 @@ export const openDataControlEditor = < overlayRef.close(); }; - const onCancel = (newState: State, overlay: OverlayRef) => { + const onCancel = (newState: Partial, overlay: OverlayRef) => { if (deepEqual(initialState, newState)) { closeOverlay(overlay); return; @@ -83,8 +82,11 @@ export const openDataControlEditor = < const overlay = services.core.overlays.openFlyout( toMountPoint( - parentApi={controlGroupApi} + controlGroupApi={controlGroupApi} initialState={initialState} + controlType={controlType} + controlId={controlId} + initialDefaultPanelTitle={initialDefaultPanelTitle} onCancel={(state) => { onCancel(state, overlay); }} diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.test.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.test.tsx index f463400b351c89..a8cd948c511c49 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.test.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.test.tsx @@ -34,9 +34,9 @@ describe('Options list sorting button', () => { const mountComponent = ({ initialState, field, - parentApi = getMockedControlGroupApi(), + controlGroupApi = getMockedControlGroupApi(), }: Pick & { - parentApi?: ControlGroupApi; + controlGroupApi?: ControlGroupApi; }) => { const component = render( { field={field} updateState={updateState} setControlEditorValid={jest.fn()} - parentApi={parentApi} + controlGroupApi={controlGroupApi} /> ); return component; @@ -85,7 +85,7 @@ describe('Options list sorting button', () => { const component = mountComponent({ initialState: getMockedState(), field: { type: 'string' } as DataViewField, - parentApi: controlGroupApi, + controlGroupApi, }); expect( component.queryByTestId('optionsListControl__searchOptionsRadioGroup') @@ -152,14 +152,14 @@ describe('Options list sorting button', () => { describe('responds to field type changing', () => { test('reset back to initial state when valid', async () => { const initialState = getMockedState({ searchTechnique: 'exact' }); - const parentApi = getMockedControlGroupApi(); + const controlGroupApi = getMockedControlGroupApi(); const component = render( ); @@ -175,7 +175,7 @@ describe('Options list sorting button', () => { field={{ type: 'ip' } as DataViewField} // initial search technique IS valid updateState={jest.fn()} setControlEditorValid={jest.fn()} - parentApi={parentApi} + controlGroupApi={controlGroupApi} /> ); @@ -187,14 +187,14 @@ describe('Options list sorting button', () => { test('if the current selection is valid, send that to the parent editor state', async () => { const initialState = getMockedState(); - const parentApi = getMockedControlGroupApi(); + const controlGroupApi = getMockedControlGroupApi(); const component = render( ); @@ -218,7 +218,7 @@ describe('Options list sorting button', () => { field={{ type: 'number' } as DataViewField} // current selected search technique IS valid, initial state is not updateState={jest.fn()} setControlEditorValid={jest.fn()} - parentApi={parentApi} + controlGroupApi={controlGroupApi} /> ); @@ -227,14 +227,14 @@ describe('Options list sorting button', () => { test('if neither the initial or current search technique is valid, revert to the default', async () => { const initialState = getMockedState({ searchTechnique: 'wildcard' }); - const parentApi = getMockedControlGroupApi(); + const controlGroupApi = getMockedControlGroupApi(); const component = render( ); @@ -250,7 +250,7 @@ describe('Options list sorting button', () => { field={{ type: 'number' } as DataViewField} // neither initial nor current search technique is valid updateState={jest.fn()} setControlEditorValid={jest.fn()} - parentApi={parentApi} + controlGroupApi={controlGroupApi} /> ); diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.tsx index e749973c99f749..48ac94c46236c4 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/options_list_control/components/options_list_editor_options.tsx @@ -71,9 +71,11 @@ export const OptionsListEditorOptions = ({ initialState, field, updateState, - parentApi, + controlGroupApi, }: CustomOptionsComponentProps) => { - const allowExpensiveQueries = useStateFromPublishingSubject(parentApi.allowExpensiveQueries$); + const allowExpensiveQueries = useStateFromPublishingSubject( + controlGroupApi.allowExpensiveQueries$ + ); const [singleSelect, setSingleSelect] = useState(initialState.singleSelect ?? false); const [runPastTimeout, setRunPastTimeout] = useState( diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx b/src/plugins/controls/public/react_controls/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx index 110de033520dec..72a754c4fabf4e 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx +++ b/src/plugins/controls/public/react_controls/controls/data_controls/range_slider/get_range_slider_control_factory.test.tsx @@ -243,7 +243,7 @@ describe('RangesliderControlApi', () => { field={{} as DataViewField} updateState={jest.fn()} setControlEditorValid={jest.fn()} - parentApi={controlGroupApi} + controlGroupApi={controlGroupApi} /> ); expect( @@ -260,7 +260,7 @@ describe('RangesliderControlApi', () => { field={{} as DataViewField} updateState={jest.fn()} setControlEditorValid={setControlEditorValid} - parentApi={controlGroupApi} + controlGroupApi={controlGroupApi} /> ); diff --git a/src/plugins/controls/public/react_controls/controls/data_controls/types.ts b/src/plugins/controls/public/react_controls/controls/data_controls/types.ts index 07025d63800716..5bff65081441f6 100644 --- a/src/plugins/controls/public/react_controls/controls/data_controls/types.ts +++ b/src/plugins/controls/public/react_controls/controls/data_controls/types.ts @@ -38,11 +38,11 @@ export type DataControlApi = DefaultControlApi & export interface CustomOptionsComponentProps< State extends DefaultDataControlState = DefaultDataControlState > { - initialState: Omit; + initialState: Partial; field: DataViewField; updateState: (newState: Partial) => void; setControlEditorValid: (valid: boolean) => void; - parentApi: ControlGroupApi; + controlGroupApi: ControlGroupApi; } export interface DataControlFactory<