diff --git a/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json b/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json index f692afb3d4501..76cf0d29ae0a6 100644 --- a/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json +++ b/src/platform/packages/shared/presentation/presentation_publishing/tsconfig.json @@ -12,6 +12,6 @@ "@kbn/expressions-plugin", "@kbn/core-execution-context-common", "@kbn/content-management-utils", - "@kbn/utility-types", + "@kbn/utility-types" ] } diff --git a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx index 79c62875ba18d..4c3efaed34a1f 100644 --- a/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/embeddable/slo/alerts/slo_alerts_embeddable_factory.tsx @@ -6,14 +6,16 @@ */ import type { 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 { Storage } from '@kbn/kibana-utils-plugin/public'; import { FetchContext, fetch$, + initializeStateManager, initializeTitleManager, + titleComparators, useBatchedPublishingSubjects, useFetchContext, } from '@kbn/presentation-publishing'; @@ -21,12 +23,13 @@ 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 { initializeUnsavedChanges } from '@kbn/presentation-containers'; import { PluginContext } from '../../../context/plugin_context'; import { SLOPublicPluginsStart, SLORepositoryClient } from '../../../types'; import { SLO_ALERTS_EMBEDDABLE_ID } from './constants'; import { SloAlertsWrapper } from './slo_alerts_wrapper'; -import { SloAlertsApi, SloAlertsEmbeddableState } from './types'; +import { EmbeddableSloProps, SloAlertsApi, SloAlertsEmbeddableState } from './types'; import { openSloConfiguration } from './slo_alerts_open_configuration'; const history = createBrowserHistory(); const queryClient = new QueryClient(); @@ -47,16 +50,9 @@ export function getAlertsEmbeddableFactory({ sloClient: SLORepositoryClient; kibanaVersion: string; }) { - const factory: ReactEmbeddableFactory< - SloAlertsEmbeddableState, - SloAlertsEmbeddableState, - SloAlertsApi - > = { + const factory: EmbeddableFactory = { type: SLO_ALERTS_EMBEDDABLE_ID, - deserializeState: (state) => { - return state.rawState as SloAlertsEmbeddableState; - }, - buildEmbeddable: async (state, buildApi, uuid, parentApi) => { + buildEmbeddable: async ({ initialState, finalizeApi, uuid, parentApi }) => { const deps = { ...coreStart, ...pluginsStart }; async function onEdit() { try { @@ -72,52 +68,66 @@ export function getAlertsEmbeddableFactory({ } } - const titleManager = initializeTitleManager(state); + const titleManager = initializeTitleManager(initialState.rawState); + const sloAlertsStateManager = initializeStateManager( + initialState.rawState, + { + slos: [], + showAllGroupByInstances: false, + } + ); const defaultTitle$ = new BehaviorSubject(getAlertsPanelTitle()); - const slos$ = new BehaviorSubject(state.slos); - const showAllGroupByInstances$ = new BehaviorSubject(state.showAllGroupByInstances); const reload$ = new Subject(); - const api = buildApi( - { - ...titleManager.api, - defaultTitle$, - getTypeDisplayName: () => - i18n.translate('xpack.slo.editSloAlertswEmbeddable.typeDisplayName', { - defaultMessage: 'configuration', - }), - isEditingEnabled: () => true, - onEdit: async () => { - onEdit(); - }, - serializeState: () => { - return { - rawState: { - ...titleManager.serialize(), - slos: slos$.getValue(), - showAllGroupByInstances: showAllGroupByInstances$.getValue(), - }, - }; - }, - getSloAlertsConfig: () => { - return { - slos: slos$.getValue(), - showAllGroupByInstances: showAllGroupByInstances$.getValue(), - }; - }, - updateSloAlertsConfig: (update) => { - slos$.next(update.slos); - showAllGroupByInstances$.next(update.showAllGroupByInstances); + + function serializeState() { + return { + rawState: { + ...titleManager.getLatestState(), + ...sloAlertsStateManager.getLatestState(), }, + }; + } + + const unsavedChangesApi = initializeUnsavedChanges({ + uuid, + parentApi, + serializeState, + anyStateChange$: merge(titleManager.anyStateChange$, sloAlertsStateManager.anyStateChange$), + getComparators: () => ({ + ...titleComparators, + slos: 'referenceEquality', + showAllGroupByInstances: 'referenceEquality', + }), + onReset: (lastSaved) => { + titleManager.reinitializeState(lastSaved?.rawState); + sloAlertsStateManager.reinitializeState(lastSaved?.rawState); }, - { - slos: [slos$, (value) => slos$.next(value)], - showAllGroupByInstances: [ - showAllGroupByInstances$, - (value) => showAllGroupByInstances$.next(value), - ], - ...titleManager.comparators, - } - ); + }); + + const api = finalizeApi({ + ...titleManager.api, + ...unsavedChangesApi, + defaultTitle$, + getTypeDisplayName: () => + i18n.translate('xpack.slo.editSloAlertswEmbeddable.typeDisplayName', { + defaultMessage: 'configuration', + }), + isEditingEnabled: () => true, + onEdit: async () => { + onEdit(); + }, + serializeState, + getSloAlertsConfig: () => { + return { + slos: sloAlertsStateManager.api.slos$.getValue(), + showAllGroupByInstances: sloAlertsStateManager.api.showAllGroupByInstances$.getValue(), + }; + }, + updateSloAlertsConfig: (update) => { + sloAlertsStateManager.api.setSlos(update.slos); + sloAlertsStateManager.api.setShowAllGroupByInstances(update.showAllGroupByInstances); + }, + }); const fetchSubscription = fetch$(api) .pipe() @@ -129,8 +139,8 @@ export function getAlertsEmbeddableFactory({ api, Component: () => { const [slos, showAllGroupByInstances] = useBatchedPublishingSubjects( - slos$, - showAllGroupByInstances$ + sloAlertsStateManager.api.slos$, + sloAlertsStateManager.api.showAllGroupByInstances$ ); const fetchContext = useFetchContext(api); const I18nContext = deps.i18n.Context; diff --git a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx index ff59eae30f80b..44fbbbfea3696 100644 --- a/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx +++ b/x-pack/solutions/observability/plugins/slo/public/ui_actions/create_alerts_panel_action.tsx @@ -42,7 +42,7 @@ export function createAddAlertsPanelAction( embeddable.addNewPanel( { panelType: SLO_ALERTS_EMBEDDABLE_ID, - initialState, + serializedState: { rawState: initialState }, }, true );