From 81a1f93e7826123c7a3c4fbc1aee0e29550fca77 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 26 Nov 2024 15:48:03 -0500 Subject: [PATCH 1/4] Change visibility to shared --- x-pack/plugins/embeddable_enhanced/kibana.jsonc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/embeddable_enhanced/kibana.jsonc b/x-pack/plugins/embeddable_enhanced/kibana.jsonc index d795afa4d7938..3b9632d4bf36c 100644 --- a/x-pack/plugins/embeddable_enhanced/kibana.jsonc +++ b/x-pack/plugins/embeddable_enhanced/kibana.jsonc @@ -5,7 +5,7 @@ "@elastic/kibana-presentation" ], "group": "platform", - "visibility": "private", + "visibility": "shared", "description": "Extends embeddable plugin with more functionality", "plugin": { "id": "embeddableEnhanced", From b2615740bc55b6a37a814f538479d65ca56eb027 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 26 Nov 2024 15:48:31 -0500 Subject: [PATCH 2/4] Add embeddable-enhanced plugin --- .../observability_solution/slo/kibana.jsonc | 32 ++++++++++--------- .../slo/public/types.ts | 2 ++ .../observability_solution/slo/tsconfig.json | 1 + 3 files changed, 20 insertions(+), 15 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/kibana.jsonc b/x-pack/plugins/observability_solution/slo/kibana.jsonc index 79302b58f8269..1a90f45c8cd9b 100644 --- a/x-pack/plugins/observability_solution/slo/kibana.jsonc +++ b/x-pack/plugins/observability_solution/slo/kibana.jsonc @@ -21,40 +21,42 @@ "charts", "dashboard", "data", - "dataViews", - "discoverShared", - "lens", "dataViewEditor", "dataViewFieldEditor", + "dataViews", + "discoverShared", + "embeddable", + "features", "fieldFormats", + "lens", + "licensing", "observability", "observabilityShared", + "presentationUtil", "ruleRegistry", + "share", "taskManager", "triggersActionsUi", - "share", - "unifiedSearch", "uiActions", - "embeddable", - "presentationUtil", - "features", - "licensing", - "usageCollection", + "unifiedSearch", + "usageCollection" ], "optionalPlugins": [ "cloud", - "serverless", "discover", + "embeddableEnhanced", "observabilityAIAssistant", - "spaces", + "security", + "serverless", + "spaces" ], "requiredBundles": [ "controls", + "embeddable", + "ingestPipelines", "kibanaReact", "kibanaUtils", - "unifiedSearch", - "embeddable", - "ingestPipelines" + "unifiedSearch" ] } } \ No newline at end of file diff --git a/x-pack/plugins/observability_solution/slo/public/types.ts b/x-pack/plugins/observability_solution/slo/public/types.ts index 1397b08a29528..44a43a3c7e585 100644 --- a/x-pack/plugins/observability_solution/slo/public/types.ts +++ b/x-pack/plugins/observability_solution/slo/public/types.ts @@ -15,6 +15,7 @@ import { DataViewFieldEditorStart } from '@kbn/data-view-field-editor-plugin/pub import type { DataViewsPublicPluginStart } from '@kbn/data-views-plugin/public'; import type { DiscoverStart } from '@kbn/discover-plugin/public'; import type { DiscoverSharedPublicStart } from '@kbn/discover-shared-plugin/public'; +import type { EmbeddableEnhancedPluginStart } from '@kbn/embeddable-enhanced-plugin/public'; import type { EmbeddableSetup, EmbeddableStart } from '@kbn/embeddable-plugin/public'; import { FieldFormatsStart } from '@kbn/field-formats-plugin/public'; import type { LensPublicStart } from '@kbn/lens-plugin/public'; @@ -80,6 +81,7 @@ export interface SLOPublicPluginsStart { discover?: DiscoverStart; discoverShared: DiscoverSharedPublicStart; embeddable: EmbeddableStart; + embeddableEnhanced?: EmbeddableEnhancedPluginStart; fieldFormats: FieldFormatsStart; lens: LensPublicStart; licensing: LicensingPluginStart; diff --git a/x-pack/plugins/observability_solution/slo/tsconfig.json b/x-pack/plugins/observability_solution/slo/tsconfig.json index 001c835fcb5cb..959026dfb583e 100644 --- a/x-pack/plugins/observability_solution/slo/tsconfig.json +++ b/x-pack/plugins/observability_solution/slo/tsconfig.json @@ -30,6 +30,7 @@ "@kbn/alerting-plugin", "@kbn/rison", "@kbn/embeddable-plugin", + "@kbn/embeddable-enhanced-plugin", "@kbn/lens-plugin", "@kbn/ui-theme", "@kbn/es-query", From 15cb8953aaecc54d6efe162e6980f3fbd6812005 Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 26 Nov 2024 15:49:19 -0500 Subject: [PATCH 3/4] Implements interfaces for enabling drilldown action --- .../slo/overview/slo_embeddable_factory.tsx | 46 ++++++++++++------- .../public/embeddable/slo/overview/types.ts | 17 ++++--- .../stats_overview_embeddable_factory.tsx | 1 + 3 files changed, 41 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx index 57de174194976..191811874b849 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx @@ -14,6 +14,7 @@ import { EuiThemeProvider } from '@kbn/kibana-react-plugin/common'; import { KibanaContextProvider } from '@kbn/kibana-react-plugin/public'; import { fetch$, + getUnchangingComparator, initializeTitles, useBatchedPublishingSubjects, } from '@kbn/presentation-publishing'; @@ -55,21 +56,15 @@ export const getOverviewEmbeddableFactory = ({ }, buildEmbeddable: async (state, buildApi, uuid, parentApi) => { const deps = { ...coreStart, ...pluginsStart }; - async function onEdit() { - try { - const { openSloConfiguration } = await import('./slo_overview_open_configuration'); - const result = await openSloConfiguration( - coreStart, - pluginsStart, - sloClient, - api.getSloGroupOverviewConfig() - ); - api.updateSloGroupOverviewConfig(result as GroupSloCustomInput); - } catch (e) { - return Promise.reject(); - } - } + const dynamicActionsApi = deps.embeddableEnhanced?.initializeReactEmbeddableDynamicActions( + uuid, + () => titlesApi.panelTitle.getValue(), + state + ); + + const maybeStopDynamicActions = dynamicActionsApi?.startDynamicActions(); + const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); const defaultTitle$ = new BehaviorSubject(getOverviewPanelTitle()); const sloId$ = new BehaviorSubject(state.sloId); @@ -83,14 +78,28 @@ export const getOverviewEmbeddableFactory = ({ const api = buildApi( { ...titlesApi, + ...(dynamicActionsApi?.dynamicActionsApi ?? {}), + supportedTriggers: () => [], defaultPanelTitle: defaultTitle$, getTypeDisplayName: () => i18n.translate('xpack.slo.editSloOverviewEmbeddableTitle.typeDisplayName', { defaultMessage: 'criteria', }), isEditingEnabled: () => api.getSloGroupOverviewConfig().overviewMode === 'groups', - onEdit: async () => { - onEdit(); + onEdit: async function onEdit() { + try { + const { openSloConfiguration } = await import('./slo_overview_open_configuration'); + + const result = await openSloConfiguration( + coreStart, + pluginsStart, + sloClient, + api.getSloGroupOverviewConfig() + ); + api.updateSloGroupOverviewConfig(result as GroupSloCustomInput); + } catch (e) { + return Promise.reject(); + } }, serializeState: () => { return { @@ -102,6 +111,7 @@ export const getOverviewEmbeddableFactory = ({ overviewMode: overviewMode$.getValue(), groupFilters: groupFilters$.getValue(), remoteName: remoteName$.getValue(), + ...(dynamicActionsApi?.serializeDynamicActions?.() ?? {}), }, }; }, @@ -126,6 +136,9 @@ export const getOverviewEmbeddableFactory = ({ remoteName: [remoteName$, (value) => remoteName$.next(value)], overviewMode: [overviewMode$, (value) => overviewMode$.next(value)], ...titleComparators, + ...(dynamicActionsApi?.dynamicActionsComparator ?? { + enhancements: getUnchangingComparator(), + }), } ); @@ -157,6 +170,7 @@ export const getOverviewEmbeddableFactory = ({ useEffect(() => { return () => { fetchSubscription.unsubscribe(); + maybeStopDynamicActions?.stopDynamicActions(); }; }, []); const renderOverview = () => { diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/types.ts b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/types.ts index 3c2866077aaa6..d79a0ecd8a4dc 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/types.ts +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/types.ts @@ -4,15 +4,16 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ +import type { DynamicActionsSerializedState } from '@kbn/embeddable-enhanced-plugin/public/plugin'; +import { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public'; +import { Filter } from '@kbn/es-query'; +import type { EmbeddableApiContext, HasSupportedTriggers } from '@kbn/presentation-publishing'; import { - SerializedTitles, - PublishesWritablePanelTitle, - PublishesPanelTitle, HasEditCapabilities, + PublishesPanelTitle, + PublishesWritablePanelTitle, + SerializedTitles, } from '@kbn/presentation-publishing'; -import type { EmbeddableApiContext } from '@kbn/presentation-publishing'; -import { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public'; -import { Filter } from '@kbn/es-query'; export type OverviewMode = 'single' | 'groups'; export type GroupBy = 'slo.tags' | 'status' | 'slo.indicator.type'; @@ -39,6 +40,7 @@ export type GroupSloCustomInput = SloConfigurationProps & { }; export type SloOverviewEmbeddableState = SerializedTitles & + Partial & Partial & Partial; @@ -46,7 +48,8 @@ export type SloOverviewApi = DefaultEmbeddableApi & PublishesWritablePanelTitle & PublishesPanelTitle & HasSloGroupOverviewConfig & - HasEditCapabilities; + HasEditCapabilities & + HasSupportedTriggers; export interface HasSloGroupOverviewConfig { getSloGroupOverviewConfig: () => GroupSloCustomInput; diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/stats_overview/stats_overview_embeddable_factory.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/stats_overview/stats_overview_embeddable_factory.tsx index 83b37f080d422..df311819399f3 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/stats_overview/stats_overview_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/embeddables/stats_overview/stats_overview_embeddable_factory.tsx @@ -67,6 +67,7 @@ export const getStatsOverviewEmbeddableFactory = ( i18n.translate('xpack.synthetics.editSloOverviewEmbeddableTitle.typeDisplayName', { defaultMessage: 'filters', }), + isEditingEnabled: () => true, onEdit: async () => { try { From b1ff551f29c018bf68970dd636784cfd60259e8f Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Tue, 26 Nov 2024 16:03:38 -0500 Subject: [PATCH 4/4] Inline variable --- .../slo/overview/slo_embeddable_factory.tsx | 391 +++++++++--------- 1 file changed, 194 insertions(+), 197 deletions(-) diff --git a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx index 191811874b849..c1b19c7381acb 100644 --- a/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx +++ b/x-pack/plugins/observability_solution/slo/public/embeddable/slo/overview/slo_embeddable_factory.tsx @@ -44,213 +44,210 @@ export const getOverviewEmbeddableFactory = ({ coreStart: CoreStart; pluginsStart: SLOPublicPluginsStart; sloClient: SLORepositoryClient; -}) => { - const factory: ReactEmbeddableFactory< - SloOverviewEmbeddableState, - SloOverviewEmbeddableState, - SloOverviewApi - > = { - type: SLO_OVERVIEW_EMBEDDABLE_ID, - deserializeState: (state) => { - return state.rawState as SloOverviewEmbeddableState; - }, - buildEmbeddable: async (state, buildApi, uuid, parentApi) => { - const deps = { ...coreStart, ...pluginsStart }; +}): ReactEmbeddableFactory< + SloOverviewEmbeddableState, + SloOverviewEmbeddableState, + SloOverviewApi +> => ({ + type: SLO_OVERVIEW_EMBEDDABLE_ID, + deserializeState: (state) => { + return state.rawState as SloOverviewEmbeddableState; + }, + buildEmbeddable: async (state, buildApi, uuid, parentApi) => { + const deps = { ...coreStart, ...pluginsStart }; - const dynamicActionsApi = deps.embeddableEnhanced?.initializeReactEmbeddableDynamicActions( - uuid, - () => titlesApi.panelTitle.getValue(), - state - ); + const dynamicActionsApi = deps.embeddableEnhanced?.initializeReactEmbeddableDynamicActions( + uuid, + () => titlesApi.panelTitle.getValue(), + state + ); - const maybeStopDynamicActions = dynamicActionsApi?.startDynamicActions(); + const maybeStopDynamicActions = dynamicActionsApi?.startDynamicActions(); - const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); - const defaultTitle$ = new BehaviorSubject(getOverviewPanelTitle()); - const sloId$ = new BehaviorSubject(state.sloId); - const sloInstanceId$ = new BehaviorSubject(state.sloInstanceId); - const showAllGroupByInstances$ = new BehaviorSubject(state.showAllGroupByInstances); - const overviewMode$ = new BehaviorSubject(state.overviewMode); - const groupFilters$ = new BehaviorSubject(state.groupFilters); - const remoteName$ = new BehaviorSubject(state.remoteName); - const reload$ = new Subject(); + const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state); + const defaultTitle$ = new BehaviorSubject(getOverviewPanelTitle()); + const sloId$ = new BehaviorSubject(state.sloId); + const sloInstanceId$ = new BehaviorSubject(state.sloInstanceId); + const showAllGroupByInstances$ = new BehaviorSubject(state.showAllGroupByInstances); + const overviewMode$ = new BehaviorSubject(state.overviewMode); + const groupFilters$ = new BehaviorSubject(state.groupFilters); + const remoteName$ = new BehaviorSubject(state.remoteName); + const reload$ = new Subject(); - const api = buildApi( - { - ...titlesApi, - ...(dynamicActionsApi?.dynamicActionsApi ?? {}), - supportedTriggers: () => [], - defaultPanelTitle: defaultTitle$, - getTypeDisplayName: () => - i18n.translate('xpack.slo.editSloOverviewEmbeddableTitle.typeDisplayName', { - defaultMessage: 'criteria', - }), - isEditingEnabled: () => api.getSloGroupOverviewConfig().overviewMode === 'groups', - onEdit: async function onEdit() { - try { - const { openSloConfiguration } = await import('./slo_overview_open_configuration'); + const api = buildApi( + { + ...titlesApi, + ...(dynamicActionsApi?.dynamicActionsApi ?? {}), + supportedTriggers: () => [], + defaultPanelTitle: defaultTitle$, + getTypeDisplayName: () => + i18n.translate('xpack.slo.editSloOverviewEmbeddableTitle.typeDisplayName', { + defaultMessage: 'criteria', + }), + isEditingEnabled: () => api.getSloGroupOverviewConfig().overviewMode === 'groups', + onEdit: async function onEdit() { + try { + const { openSloConfiguration } = await import('./slo_overview_open_configuration'); - const result = await openSloConfiguration( - coreStart, - pluginsStart, - sloClient, - api.getSloGroupOverviewConfig() - ); - api.updateSloGroupOverviewConfig(result as GroupSloCustomInput); - } catch (e) { - return Promise.reject(); - } - }, - serializeState: () => { - return { - rawState: { - ...serializeTitles(), - sloId: sloId$.getValue(), - sloInstanceId: sloInstanceId$.getValue(), - showAllGroupByInstances: showAllGroupByInstances$.getValue(), - overviewMode: overviewMode$.getValue(), - groupFilters: groupFilters$.getValue(), - remoteName: remoteName$.getValue(), - ...(dynamicActionsApi?.serializeDynamicActions?.() ?? {}), - }, - }; - }, - getSloGroupOverviewConfig: () => { - return { - groupFilters: groupFilters$.getValue(), + const result = await openSloConfiguration( + coreStart, + pluginsStart, + sloClient, + api.getSloGroupOverviewConfig() + ); + api.updateSloGroupOverviewConfig(result as GroupSloCustomInput); + } catch (e) { + return Promise.reject(); + } + }, + serializeState: () => { + return { + rawState: { + ...serializeTitles(), + sloId: sloId$.getValue(), + sloInstanceId: sloInstanceId$.getValue(), + showAllGroupByInstances: showAllGroupByInstances$.getValue(), overviewMode: overviewMode$.getValue(), - }; - }, - updateSloGroupOverviewConfig: (update: GroupSloCustomInput) => { - groupFilters$.next(update.groupFilters); - }, + groupFilters: groupFilters$.getValue(), + remoteName: remoteName$.getValue(), + ...(dynamicActionsApi?.serializeDynamicActions?.() ?? {}), + }, + }; }, - { - sloId: [sloId$, (value) => sloId$.next(value)], - sloInstanceId: [sloInstanceId$, (value) => sloInstanceId$.next(value)], - groupFilters: [groupFilters$, (value) => groupFilters$.next(value)], - showAllGroupByInstances: [ - showAllGroupByInstances$, - (value) => showAllGroupByInstances$.next(value), - ], - remoteName: [remoteName$, (value) => remoteName$.next(value)], - overviewMode: [overviewMode$, (value) => overviewMode$.next(value)], - ...titleComparators, - ...(dynamicActionsApi?.dynamicActionsComparator ?? { - enhancements: getUnchangingComparator(), - }), - } - ); - - const fetchSubscription = fetch$(api) - .pipe() - .subscribe((next) => { - reload$.next(next.isReload); - }); + getSloGroupOverviewConfig: () => { + return { + groupFilters: groupFilters$.getValue(), + overviewMode: overviewMode$.getValue(), + }; + }, + updateSloGroupOverviewConfig: (update: GroupSloCustomInput) => { + groupFilters$.next(update.groupFilters); + }, + }, + { + sloId: [sloId$, (value) => sloId$.next(value)], + sloInstanceId: [sloInstanceId$, (value) => sloInstanceId$.next(value)], + groupFilters: [groupFilters$, (value) => groupFilters$.next(value)], + showAllGroupByInstances: [ + showAllGroupByInstances$, + (value) => showAllGroupByInstances$.next(value), + ], + remoteName: [remoteName$, (value) => remoteName$.next(value)], + overviewMode: [overviewMode$, (value) => overviewMode$.next(value)], + ...titleComparators, + ...(dynamicActionsApi?.dynamicActionsComparator ?? { + enhancements: getUnchangingComparator(), + }), + } + ); - return { - api, - Component: () => { - const [ - sloId, - sloInstanceId, - showAllGroupByInstances, - overviewMode, - groupFilters, - remoteName, - ] = useBatchedPublishingSubjects( - sloId$, - sloInstanceId$, - showAllGroupByInstances$, - overviewMode$, - groupFilters$, - remoteName$ - ); + const fetchSubscription = fetch$(api) + .pipe() + .subscribe((next) => { + reload$.next(next.isReload); + }); - useEffect(() => { - return () => { - fetchSubscription.unsubscribe(); - maybeStopDynamicActions?.stopDynamicActions(); - }; - }, []); - const renderOverview = () => { - if (overviewMode === 'groups') { - const groupBy = groupFilters?.groupBy ?? 'status'; - const kqlQuery = groupFilters?.kqlQuery ?? ''; - const groups = groupFilters?.groups ?? []; - return ( -
css` - width: 100%; - padding: ${euiTheme.size.xs} ${euiTheme.size.base}; - overflow: scroll; + return { + api, + Component: () => { + const [ + sloId, + sloInstanceId, + showAllGroupByInstances, + overviewMode, + groupFilters, + remoteName, + ] = useBatchedPublishingSubjects( + sloId$, + sloInstanceId$, + showAllGroupByInstances$, + overviewMode$, + groupFilters$, + remoteName$ + ); - .euiAccordion__buttonContent { - min-width: ${euiTheme.base * 6}px; - } - `} - > - - css` - margin-top: ${euiTheme.base * 1.25}px; - `} - > - - - -
- ); - } else { - return ( - - ); - } + useEffect(() => { + return () => { + fetchSubscription.unsubscribe(); + maybeStopDynamicActions?.stopDynamicActions(); }; + }, []); + const renderOverview = () => { + if (overviewMode === 'groups') { + const groupBy = groupFilters?.groupBy ?? 'status'; + const kqlQuery = groupFilters?.kqlQuery ?? ''; + const groups = groupFilters?.groups ?? []; + return ( +
css` + width: 100%; + padding: ${euiTheme.size.xs} ${euiTheme.size.base}; + overflow: scroll; - const queryClient = new QueryClient(); - - return ( - - - - + + css` + margin-top: ${euiTheme.base * 1.25}px; + `} > - - {showAllGroupByInstances ? ( - - ) : ( - renderOverview() - )} - - - - - - ); - }, - }; - }, - }; - return factory; -}; + + + +
+ ); + } else { + return ( + + ); + } + }; + + const queryClient = new QueryClient(); + + return ( + + + + + + {showAllGroupByInstances ? ( + + ) : ( + renderOverview() + )} + + + + + + ); + }, + }; + }, +});