Skip to content

Commit

Permalink
[8.x] [Lens][Embeddable] Unify internal api into a single object (#20…
Browse files Browse the repository at this point in the history
…4194) (#204776)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[Lens][Embeddable] Unify internal api into a single object
(#204194)](#204194)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Marco
Liberati","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-12-18T15:15:43Z","message":"[Lens][Embeddable]
Unify internal api into a single object (#204194)\n\n##
Summary\r\n\r\nFixes #198753 \r\n\r\nInitially `visualizationContext`
was migrated from the legacy system\r\n\"as-is\" when refactoring to the
new system.\r\nThis PR merges the `visualizationContextHelpers` within
the Lens\r\n`internalApi` to avoid:\r\n* attributes unsync (it rely on
the `attributes` variable which is hold\r\nby the `internalApi`
already)\r\n* single place to find internal variables\r\n\r\nTook also
the opportunity to simplify the mocks here:\r\n* use the actual
implementation for the internalApi vs mocks\r\n * this would simplify
also the maintenance of types in the future\r\n* adapted the tests to
use the new implementation and
`internalApi`","sha":"6490c45550446a79794135ae66e4b75e473c38f5","branchLabelMapping":{"^v9.0.0$":"main","^v8.18.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Team:Visualizations","release_note:skip","Feature:Lens","v9.0.0","backport:prev-minor"],"title":"[Lens][Embeddable]
Unify internal api into a single
object","number":204194,"url":"https://github.com/elastic/kibana/pull/204194","mergeCommit":{"message":"[Lens][Embeddable]
Unify internal api into a single object (#204194)\n\n##
Summary\r\n\r\nFixes #198753 \r\n\r\nInitially `visualizationContext`
was migrated from the legacy system\r\n\"as-is\" when refactoring to the
new system.\r\nThis PR merges the `visualizationContextHelpers` within
the Lens\r\n`internalApi` to avoid:\r\n* attributes unsync (it rely on
the `attributes` variable which is hold\r\nby the `internalApi`
already)\r\n* single place to find internal variables\r\n\r\nTook also
the opportunity to simplify the mocks here:\r\n* use the actual
implementation for the internalApi vs mocks\r\n * this would simplify
also the maintenance of types in the future\r\n* adapted the tests to
use the new implementation and
`internalApi`","sha":"6490c45550446a79794135ae66e4b75e473c38f5"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/204194","number":204194,"mergeCommit":{"message":"[Lens][Embeddable]
Unify internal api into a single object (#204194)\n\n##
Summary\r\n\r\nFixes #198753 \r\n\r\nInitially `visualizationContext`
was migrated from the legacy system\r\n\"as-is\" when refactoring to the
new system.\r\nThis PR merges the `visualizationContextHelpers` within
the Lens\r\n`internalApi` to avoid:\r\n* attributes unsync (it rely on
the `attributes` variable which is hold\r\nby the `internalApi`
already)\r\n* single place to find internal variables\r\n\r\nTook also
the opportunity to simplify the mocks here:\r\n* use the actual
implementation for the internalApi vs mocks\r\n * this would simplify
also the maintenance of types in the future\r\n* adapted the tests to
use the new implementation and
`internalApi`","sha":"6490c45550446a79794135ae66e4b75e473c38f5"}}]}]
BACKPORT-->

Co-authored-by: Marco Liberati <[email protected]>
  • Loading branch information
kibanamachine and dej611 authored Dec 18, 2024
1 parent dee44c3 commit 5f127c9
Show file tree
Hide file tree
Showing 11 changed files with 87 additions and 125 deletions.
16 changes: 4 additions & 12 deletions x-pack/plugins/lens/public/react_embeddable/data_loader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,7 @@ import {
import fastIsEqual from 'fast-deep-equal';
import { pick } from 'lodash';
import { getEditPath } from '../../common/constants';
import type {
GetStateType,
LensApi,
LensInternalApi,
LensPublicCallbacks,
VisualizationContextHelper,
} from './types';
import type { GetStateType, LensApi, LensInternalApi, LensPublicCallbacks } from './types';
import { getExpressionRendererParams } from './expressions/expression_params';
import type { LensEmbeddableStartServices } from './types';
import { prepareCallbacks } from './expressions/callbacks';
Expand Down Expand Up @@ -84,7 +78,6 @@ export function loadEmbeddableData(
parentApi: unknown,
internalApi: LensInternalApi,
services: LensEmbeddableStartServices,
{ getVisualizationContext, updateVisualizationContext }: VisualizationContextHelper,
metaInfo?: SharingSavedObjectProps
) {
const { onLoad, onBeforeBadgesRender, ...callbacks } = apiHasLensComponentCallbacks(parentApi)
Expand All @@ -103,7 +96,6 @@ export function loadEmbeddableData(
} = buildUserMessagesHelpers(
api,
internalApi,
getVisualizationContext,
services,
onBeforeBadgesRender,
services.spaces,
Expand Down Expand Up @@ -174,7 +166,7 @@ export function loadEmbeddableData(
};

const onDataCallback = (adapters: Partial<DefaultInspectorAdapters> | undefined) => {
updateVisualizationContext({
internalApi.updateVisualizationContext({
activeData: adapters?.tables?.tables,
});
// data has loaded
Expand Down Expand Up @@ -243,8 +235,8 @@ export function loadEmbeddableData(

// update the visualization context before anything else
// as it will be used to compute blocking errors also in case of issues
updateVisualizationContext({
doc: currentState.attributes,
internalApi.updateVisualizationContext({
activeAttributes: currentState.attributes,
mergedSearchContext: params?.searchContext || {},
...rest,
});
Expand Down
2 changes: 1 addition & 1 deletion x-pack/plugins/lens/public/react_embeddable/helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ export function createEmptyLensState(
query: query || { query: '', language: 'kuery' },
filters: filters || [],
internalReferences: [],
datasourceStates: { ...(isTextBased ? { text_based: {} } : { form_based: {} }) },
datasourceStates: { ...(isTextBased ? { textBased: {} } : { formBased: {} }) },
visualization: {},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import {
getLensApiMock,
makeEmbeddableServices,
getLensRuntimeStateMock,
getVisualizationContextHelperMock,
createUnifiedSearchApi,
getLensInternalApiMock,
} from '../mocks';
import { createEmptyLensState } from '../helper';
const DATAVIEW_ID = 'myDataView';
Expand All @@ -40,11 +40,17 @@ function setupActionsApi(
) {
const services = makeEmbeddableServices(undefined, undefined, {
visOverrides: { id: 'lnsXY' },
dataOverrides: { id: 'form_based' },
dataOverrides: { id: 'formBased' },
});
const uuid = faker.random.uuid();
const runtimeState = getLensRuntimeStateMock(stateOverrides);
const apiMock = getLensApiMock();
// create the internal API and customize internal state
const internalApi = getLensInternalApiMock();
internalApi.updateVisualizationContext({
...contextOverrides,
activeAttributes: runtimeState.attributes,
});

const { api } = initializeActionApi(
uuid,
Expand All @@ -53,7 +59,7 @@ function setupActionsApi(
createUnifiedSearchApi(),
pick(apiMock, ['timeRange$']),
pick(apiMock, ['panelTitle']),
getVisualizationContextHelperMock(stateOverrides?.attributes, contextOverrides),
internalApi,
{
...services,
data: {
Expand Down Expand Up @@ -85,6 +91,7 @@ describe('Dashboard actions', () => {
describe('Explore in Discover', () => {
// make it pass the basic check on viewUnderlyingData
const visualizationContextMockOverrides = {
activeAttributes: undefined,
mergedSearchContext: {},
indexPatterns: {
[DATAVIEW_ID]: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ import { buildObservableVariable, isTextBasedLanguage } from '../helper';
import type {
GetStateType,
LensEmbeddableStartServices,
LensInternalApi,
LensRuntimeState,
ViewInDiscoverCallbacks,
ViewUnderlyingDataArgs,
VisualizationContextHelper,
} from '../types';
import { getActiveDatasourceIdFromDoc, getActiveVisualizationIdFromDoc } from '../../utils';

Expand Down Expand Up @@ -120,7 +120,7 @@ function getViewUnderlyingDataArgs({

function loadViewUnderlyingDataArgs(
state: LensRuntimeState,
{ getVisualizationContext }: VisualizationContextHelper,
{ getVisualizationContext }: LensInternalApi,
searchContextApi: { timeRange$: PublishingSubject<TimeRange | undefined> },
parentApi: unknown,
{
Expand All @@ -132,16 +132,21 @@ function loadViewUnderlyingDataArgs(
visualizationMap,
}: LensEmbeddableStartServices
) {
const { doc, activeData, activeDatasourceState, activeVisualizationState, indexPatterns } =
getVisualizationContext();
const activeVisualizationId = getActiveVisualizationIdFromDoc(doc);
const activeDatasourceId = getActiveDatasourceIdFromDoc(doc);
const {
activeAttributes,
activeData,
activeDatasourceState,
activeVisualizationState,
indexPatterns,
} = getVisualizationContext();
const activeVisualizationId = getActiveVisualizationIdFromDoc(activeAttributes);
const activeDatasourceId = getActiveDatasourceIdFromDoc(activeAttributes);
const activeVisualization = activeVisualizationId
? visualizationMap[activeVisualizationId]
: undefined;
const activeDatasource = activeDatasourceId ? datasourceMap[activeDatasourceId] : undefined;
if (
!doc ||
!activeAttributes ||
!activeData ||
!activeDatasource ||
!activeDatasourceState ||
Expand Down Expand Up @@ -199,7 +204,7 @@ function loadViewUnderlyingDataArgs(

function createViewUnderlyingDataApis(
getState: GetStateType,
visualizationContextHelper: VisualizationContextHelper,
internalApi: LensInternalApi,
searchContextApi: { timeRange$: PublishingSubject<TimeRange | undefined> },
parentApi: unknown,
services: LensEmbeddableStartServices
Expand All @@ -213,7 +218,7 @@ function createViewUnderlyingDataApis(
loadViewUnderlyingData: () => {
viewUnderlyingDataArgs = loadViewUnderlyingDataArgs(
getState(),
visualizationContextHelper,
internalApi,
searchContextApi,
parentApi,
services
Expand All @@ -237,7 +242,7 @@ export function initializeActionApi(
parentApi: unknown,
searchContextApi: { timeRange$: PublishingSubject<TimeRange | undefined> },
titleApi: { panelTitle: PublishingSubject<string | undefined> },
visualizationContextHelper: VisualizationContextHelper,
internalApi: LensInternalApi,
services: LensEmbeddableStartServices
): {
api: ViewInDiscoverCallbacks & HasDynamicActions;
Expand All @@ -257,7 +262,7 @@ export function initializeActionApi(
...(isTextBasedLanguage(initialState) ? {} : dynamicActionsApi?.dynamicActionsApi ?? {}),
...createViewUnderlyingDataApis(
getLatestState,
visualizationContextHelper,
internalApi,
searchContextApi,
parentApi,
services
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import type {
LensInternalApi,
LensOverrides,
LensRuntimeState,
VisualizationContext,
} from '../types';
import { apiHasAbortController, apiHasLensComponentProps } from '../type_guards';
import type { UserMessage } from '../../types';
Expand Down Expand Up @@ -52,6 +53,18 @@ export function initializeInternalApi(
// the isNewPanel won't be serialized so it will be always false after the edit panel closes applying the changes
const isNewlyCreated$ = new BehaviorSubject<boolean>(initialState.isNewPanel || false);

const visualizationContext$ = new BehaviorSubject<VisualizationContext>({
// doc can point to a different set of attributes for the visualization
// i.e. when inline editing or applying a suggestion
activeAttributes: initialState.attributes,
mergedSearchContext: {},
indexPatterns: {},
indexPatternRefs: [],
activeVisualizationState: undefined,
activeDatasourceState: undefined,
activeData: undefined,
});

// No need to expose anything at public API right now, that would happen later on
// where each initializer will pick what it needs and publish it
return {
Expand All @@ -65,6 +78,8 @@ export function initializeInternalApi(
renderCount$,
isNewlyCreated$,
dataViews: dataViews$,
messages$,
validationMessages$,
dispatchError: () => {
hasRenderCompleted$.next(true);
renderCount$.next(renderCount$.getValue() + 1);
Expand All @@ -82,9 +97,7 @@ export function initializeInternalApi(
updateAbortController: (abortController: AbortController | undefined) =>
expressionAbortController$.next(abortController),
updateDataViews: (dataViews: DataView[] | undefined) => dataViews$.next(dataViews),
messages$,
updateMessages: (newMessages: UserMessage[]) => messages$.next(newMessages),
validationMessages$,
updateValidationMessages: (newMessages: UserMessage[]) => validationMessages$.next(newMessages),
resetAllMessages: () => {
messages$.next([]);
Expand Down Expand Up @@ -116,5 +129,12 @@ export function initializeInternalApi(

return displayOptions;
},
getVisualizationContext: () => visualizationContext$.getValue(),
updateVisualizationContext: (newVisualizationContext: Partial<VisualizationContext>) => {
visualizationContext$.next({
...visualizationContext$.getValue(),
...newVisualizationContext,
});
},
};
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { initializeInspector } from './initializers/initialize_inspector';
import { initializeDashboardServices } from './initializers/initialize_dashboard_services';
import { initializeInternalApi } from './initializers/initialize_internal_api';
import { initializeSearchContext } from './initializers/initialize_search_context';
import { initializeVisualizationContext } from './initializers/initialize_visualization_context';
import { initializeActionApi } from './initializers/initialize_actions';
import { initializeIntegrations } from './initializers/initialize_integrations';
import { initializeStateManagement } from './initializers/initialize_state_management';
Expand Down Expand Up @@ -61,8 +60,6 @@ export const createLensEmbeddableFactory = (
*/
const internalApi = initializeInternalApi(initialState, parentApi, services);

const visualizationContextHelper = initializeVisualizationContext(internalApi);

/**
* Initialize various configurations required to build all the required
* parts for the Lens embeddable.
Expand Down Expand Up @@ -108,7 +105,7 @@ export const createLensEmbeddableFactory = (
parentApi,
searchContextConfig.api,
dashboardConfig.api,
visualizationContextHelper,
internalApi,
services
);

Expand Down Expand Up @@ -165,8 +162,7 @@ export const createLensEmbeddableFactory = (
api,
parentApi,
internalApi,
services,
visualizationContextHelper
services
);

const onUnmount = () => {
Expand Down
Loading

0 comments on commit 5f127c9

Please sign in to comment.