Skip to content

Commit c521c1c

Browse files
authored
[Lens][Embeddable] Apply the correct references for filters (#204047)
## Summary Fixes #180726 Fix the filter references when inline editing with the correct ones. I've tried to reduce the fix to a minimal `extract` wrapper, but unfortunately that is not possible due to some shared logic who rely on the passed filters references and need to be injected. So, why not injecting them and instead rely on the search context api? Right now there's no difference, but formally the `api.filters$` is the right place to get the latest version, and if in the future the `Edit filters` flows would change, this api should be the go-to place to have the right value. Why not adding a FTR? There's a bigger problem with the panel filters action who has a dynamic `data-test-subj` value which is impossible to get right now. I would rather prefer to fix that first and then add some tests in general for multiple scenarios in Lens. ## Testing it locally * Create a viz with a filter in the editor, save and return to dashboard * Check the filters are shown correctly in the dashboard panel * Edit inline and change the chart type. Apply changes * Check the filters are shown correctly * Now "edit" in the editor without changing anything * Check the filter can be edited correctly (no empty popover) ✅ or 💥 * Save and return to dashboard * Check the filters are shown correctly ✅ or 💥
1 parent 7678141 commit c521c1c

File tree

3 files changed

+58
-10
lines changed

3 files changed

+58
-10
lines changed

x-pack/plugins/lens/public/react_embeddable/initializers/initialize_edit.tsx

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import { setupPanelManagement } from '../inline_editing/panel_management';
3737
import { mountInlineEditPanel } from '../inline_editing/mount';
3838
import { StateManagementConfig } from './initialize_state_management';
3939
import { apiPublishesInlineEditingCapabilities } from '../type_guards';
40+
import { SearchContextConfig } from './initialize_search_context';
4041

4142
function getSupportedTriggers(
4243
getState: GetStateType,
@@ -61,6 +62,7 @@ export function initializeEditApi(
6162
internalApi: LensInternalApi,
6263
stateApi: StateManagementConfig['api'],
6364
inspectorApi: LensInspectorAdapters,
65+
searchContextApi: SearchContextConfig['api'],
6466
isTextBasedLanguage: (currentState: LensRuntimeState) => boolean,
6567
startDependencies: LensEmbeddableStartServices,
6668
parentApi?: unknown
@@ -126,9 +128,34 @@ export function initializeEditApi(
126128
stateApi.updateSavedObjectId(newState.savedObjectId);
127129
};
128130

131+
// Wrap the getState() when inline editing and make sure that the filters in the attributes
132+
// are properly injected with the correct references to avoid issues when saving/navigating to the full editor
133+
const getStateWithInjectedFilters = () => {
134+
const currentState = getState();
135+
// use the search context api here for filters for 2 reasons:
136+
// * the filters here have the correct references already injected
137+
// * the edit filters flow may change in the future and this is the right place to get the filters
138+
const currentFilters = searchContextApi.filters$.getValue() ?? [];
139+
// if there are no filters, avoid to copy the attributes
140+
if (!currentFilters.length) {
141+
return currentState;
142+
}
143+
// otherwise make sure to inject the references into filters
144+
return {
145+
...currentState,
146+
attributes: {
147+
...currentState.attributes,
148+
state: {
149+
...currentState.attributes.state,
150+
filters: currentFilters,
151+
},
152+
},
153+
};
154+
};
155+
129156
const openInlineEditor = prepareInlineEditPanel(
130157
initialState,
131-
getState,
158+
getStateWithInjectedFilters,
132159
updateState,
133160
internalApi,
134161
panelManagementApi,
@@ -205,6 +232,9 @@ export function initializeEditApi(
205232
const rootEmbeddable = parentApi;
206233
const overlayTracker = tracksOverlays(rootEmbeddable) ? rootEmbeddable : undefined;
207234
const ConfigPanel = await openInlineEditor({
235+
// the getState() here contains the wrong filters references
236+
// but the input attributes are correct as openInlineEditor() handler is using
237+
// the getStateWithInjectedFilters() function
208238
onApply: (attributes: LensRuntimeState['attributes']) =>
209239
updateState({ ...getState(), attributes }),
210240
// restore the first state found when the panel opened

x-pack/plugins/lens/public/react_embeddable/initializers/initialize_search_context.ts

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,26 @@ import {
1818
apiPublishesSearchSession,
1919
} from '@kbn/presentation-publishing/interfaces/fetch/publishes_search_session';
2020
import { buildObservableVariable } from '../helper';
21-
import { LensInternalApi, LensRuntimeState, LensUnifiedSearchContext } from '../types';
21+
import {
22+
LensEmbeddableStartServices,
23+
LensInternalApi,
24+
LensRuntimeState,
25+
LensUnifiedSearchContext,
26+
} from '../types';
2227

23-
export function initializeSearchContext(
24-
initialState: LensRuntimeState,
25-
internalApi: LensInternalApi,
26-
parentApi: unknown
27-
): {
28+
export interface SearchContextConfig {
2829
api: PublishesUnifiedSearch & PublishesSearchSession;
2930
comparators: StateComparators<LensUnifiedSearchContext>;
3031
serialize: () => LensUnifiedSearchContext;
3132
cleanup: () => void;
32-
} {
33+
}
34+
35+
export function initializeSearchContext(
36+
initialState: LensRuntimeState,
37+
internalApi: LensInternalApi,
38+
parentApi: unknown,
39+
{ injectFilterReferences }: LensEmbeddableStartServices
40+
): SearchContextConfig {
3341
const [searchSessionId$] = buildObservableVariable<string | undefined>(
3442
apiPublishesSearchSession(parentApi) ? parentApi.searchSessionId$ : undefined
3543
);
@@ -38,7 +46,10 @@ export function initializeSearchContext(
3846

3947
const [lastReloadRequestTime] = buildObservableVariable<number | undefined>(undefined);
4048

41-
const [filters$] = buildObservableVariable<Filter[] | undefined>(attributes.state.filters);
49+
// Make sure the panel access the filters with the correct references
50+
const [filters$] = buildObservableVariable<Filter[] | undefined>(
51+
injectFilterReferences(attributes.state.filters, attributes.references)
52+
);
4253

4354
const [query$] = buildObservableVariable<Query | AggregateQuery | undefined>(
4455
attributes.state.query

x-pack/plugins/lens/public/react_embeddable/lens_embeddable.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,19 +84,26 @@ export const createLensEmbeddableFactory = (
8484

8585
const inspectorConfig = initializeInspector(services);
8686

87+
const searchContextConfig = initializeSearchContext(
88+
initialState,
89+
internalApi,
90+
parentApi,
91+
services
92+
);
93+
8794
const editConfig = initializeEditApi(
8895
uuid,
8996
initialState,
9097
getState,
9198
internalApi,
9299
stateConfig.api,
93100
inspectorConfig.api,
101+
searchContextConfig.api,
94102
isTextBasedLanguage,
95103
services,
96104
parentApi
97105
);
98106

99-
const searchContextConfig = initializeSearchContext(initialState, internalApi, parentApi);
100107
const integrationsConfig = initializeIntegrations(getState, services);
101108
const actionsConfig = initializeActionApi(
102109
uuid,

0 commit comments

Comments
 (0)