[Serialized State Only] [SLO] Convert SLO Error Budget embeddable to serialized state only (#218464)

_This PR does not need to be reviewed by external teams. This PR merges
into a feature branch that Kibana presentation team is working on to
convert the embeddable framework to only expose serialized state. Your
team will be pinged for review once the work is complete and the final
PR opens that merges the feature branch into main._

## Summary

Convert SLO Error Budget embeddable to serialized state only

## Testing this PR

Create an SLO using the "How to Test" section in the description of
[this PR](https://github.com/elastic/kibana/pull/179147).
This commit is contained in:
Nick Peihl 2025-04-18 15:11:34 -04:00 committed by GitHub
parent 6deb95d780
commit 55a8c7ff96
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 52 additions and 37 deletions

View file

@ -5,24 +5,27 @@
* 2.0.
*/
import { CoreStart } from '@kbn/core-lifecycle-browser';
import { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
import { EmbeddableFactory } from '@kbn/embeddable-plugin/public';
import { i18n } from '@kbn/i18n';
import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public';
import { initializeUnsavedChanges } from '@kbn/presentation-containers';
import {
fetch$,
initializeStateManager,
initializeTitleManager,
titleComparators,
useBatchedPublishingSubjects,
} from '@kbn/presentation-publishing';
import { Router } from '@kbn/shared-ux-router';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import { createBrowserHistory } from 'history';
import React, { useEffect } from 'react';
import { BehaviorSubject, Subject } from 'rxjs';
import { BehaviorSubject, Subject, merge } from 'rxjs';
import { PluginContext } from '../../../context/plugin_context';
import { SLOPublicPluginsStart, SLORepositoryClient } from '../../../types';
import { SLO_ERROR_BUDGET_ID } from './constants';
import { SloErrorBudget } from './error_budget_burn_down';
import { ErrorBudgetApi, SloErrorBudgetEmbeddableState } from './types';
import { ErrorBudgetApi, ErrorBudgetCustomInput, SloErrorBudgetEmbeddableState } from './types';
const getErrorBudgetPanelTitle = () =>
i18n.translate('xpack.slo.errorBudgetEmbeddable.title', {
@ -38,43 +41,52 @@ export const getErrorBudgetEmbeddableFactory = ({
pluginsStart: SLOPublicPluginsStart;
sloClient: SLORepositoryClient;
}) => {
const factory: ReactEmbeddableFactory<
SloErrorBudgetEmbeddableState,
SloErrorBudgetEmbeddableState,
ErrorBudgetApi
> = {
const factory: EmbeddableFactory<SloErrorBudgetEmbeddableState, ErrorBudgetApi> = {
type: SLO_ERROR_BUDGET_ID,
deserializeState: (state) => {
return state.rawState as SloErrorBudgetEmbeddableState;
},
buildEmbeddable: async (state, buildApi, uuid, parentApi) => {
buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => {
const deps = { ...coreStart, ...pluginsStart };
const titleManager = initializeTitleManager(state);
const titleManager = initializeTitleManager(initialState.rawState);
const defaultTitle$ = new BehaviorSubject<string | undefined>(getErrorBudgetPanelTitle());
const sloId$ = new BehaviorSubject(state.sloId);
const sloInstanceId$ = new BehaviorSubject(state.sloInstanceId);
const reload$ = new Subject<boolean>();
const api = buildApi(
const sloErrorBudgetManager = initializeStateManager<ErrorBudgetCustomInput>(
initialState.rawState,
{
...titleManager.api,
defaultTitle$,
serializeState: () => {
return {
rawState: {
...titleManager.serialize(),
sloId: sloId$.getValue(),
sloInstanceId: sloInstanceId$.getValue(),
},
};
},
},
{
sloId: [sloId$, (value) => sloId$.next(value)],
sloInstanceId: [sloInstanceId$, (value) => sloInstanceId$.next(value)],
...titleManager.comparators,
sloId: undefined,
sloInstanceId: undefined,
}
);
const reload$ = new Subject<boolean>();
function serializeState() {
return {
rawState: {
...titleManager.getLatestState(),
...sloErrorBudgetManager.getLatestState(),
},
};
}
const unsavedChangesApi = initializeUnsavedChanges({
uuid,
parentApi,
serializeState,
anyStateChange$: merge(titleManager.anyStateChange$, sloErrorBudgetManager.anyStateChange$),
getComparators: () => ({
...titleComparators,
sloId: 'referenceEquality',
sloInstanceId: 'referenceEquality',
}),
onReset: (lastState) => {
sloErrorBudgetManager.reinitializeState(lastState?.rawState);
titleManager.reinitializeState(lastState?.rawState);
},
});
const api = finalizeApi({
...titleManager.api,
...unsavedChangesApi,
defaultTitle$,
serializeState,
});
const fetchSubscription = fetch$(api)
.pipe()
@ -85,7 +97,10 @@ export const getErrorBudgetEmbeddableFactory = ({
return {
api,
Component: () => {
const [sloId, sloInstanceId] = useBatchedPublishingSubjects(sloId$, sloInstanceId$);
const [sloId, sloInstanceId] = useBatchedPublishingSubjects(
sloErrorBudgetManager.api.sloId$,
sloErrorBudgetManager.api.sloInstanceId$
);
useEffect(() => {
return () => {

View file

@ -25,7 +25,7 @@ export interface EmbeddableSloProps {
onRenderComplete?: () => void;
}
interface ErrorBudgetCustomInput {
export interface ErrorBudgetCustomInput {
sloId: string | undefined;
sloInstanceId: string | undefined;
}

View file

@ -41,7 +41,7 @@ export function createAddErrorBudgetPanelAction(
embeddable.addNewPanel(
{
panelType: SLO_ERROR_BUDGET_ID,
initialState,
serializedState: { rawState: initialState },
},
true
);