diff --git a/src/plugins/navigation_embeddable/public/components/navigation_embeddable_component.tsx b/src/plugins/navigation_embeddable/public/components/navigation_embeddable_component.tsx index 544f5593541df..c6423f0c529d2 100644 --- a/src/plugins/navigation_embeddable/public/components/navigation_embeddable_component.tsx +++ b/src/plugins/navigation_embeddable/public/components/navigation_embeddable_component.tsx @@ -7,10 +7,7 @@ */ import React, { useMemo } from 'react'; - import { EuiListGroup, EuiPanel } from '@elastic/eui'; - -import { NavigationEmbeddableByValueInput } from '../embeddable/types'; import { useNavigationEmbeddable } from '../embeddable/navigation_embeddable'; import { ExternalLinkComponent } from './external_link/external_link_component'; import { DashboardLinkComponent } from './dashboard_link/dashboard_link_component'; @@ -25,12 +22,8 @@ import './navigation_embeddable_component.scss'; export const NavigationEmbeddableComponent = () => { const navEmbeddable = useNavigationEmbeddable(); - const links = navEmbeddable.select( - (state) => (state.explicitInput as NavigationEmbeddableByValueInput).attributes?.links - ); - const layout = navEmbeddable.select( - (state) => (state.explicitInput as NavigationEmbeddableByValueInput).attributes?.layout - ); + const links = navEmbeddable.select((state) => state.componentState.links); + const layout = navEmbeddable.select((state) => state.componentState.layout); const orderedLinks = useMemo(() => { if (!links) return []; diff --git a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable.tsx b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable.tsx index 58a665488b825..a275ee26fe1fc 100644 --- a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable.tsx +++ b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable.tsx @@ -7,7 +7,8 @@ */ import React, { createContext, useContext } from 'react'; -import { Subscription } from 'rxjs'; +import { Subscription, distinctUntilChanged, skip } from 'rxjs'; +import deepEqual from 'fast-deep-equal'; import { AttributeService, @@ -92,7 +93,9 @@ export class NavigationEmbeddable >({ embeddable: this, reducers: navigationEmbeddableReducers, - initialComponentState: {}, + initialComponentState: { + title: '', + }, }); this.select = reduxEmbeddableTools.select; @@ -101,24 +104,31 @@ export class NavigationEmbeddable this.cleanupStateTools = reduxEmbeddableTools.cleanup; this.onStateChange = reduxEmbeddableTools.onStateChange; - this.initializeSavedLinks(initialInput) + this.initializeSavedLinks() .then(() => this.setInitializationFinished()) .catch((e: Error) => this.onFatalError(e)); + + // By-value panels should update the componentState when input changes + this.subscriptions.add( + this.getInput$() + .pipe(distinctUntilChanged(deepEqual), skip(1)) + .subscribe(async () => await this.initializeSavedLinks()) + ); } - private async initializeSavedLinks(input: NavigationEmbeddableInput) { - const { attributes } = await this.attributeService.unwrapAttributes(input); + private async initializeSavedLinks() { + const { attributes } = await this.attributeService.unwrapAttributes(this.getInput()); if (this.isDestroyed) return; // TODO handle metaInfo - this.updateInput({ attributes }); + this.dispatch.setAttributes(attributes); await this.initializeOutput(); } private async initializeOutput() { - const { attributes } = this.getInput() as NavigationEmbeddableByValueInput; + const attributes = this.getState().componentState; const { title, description } = this.getInput(); this.updateOutput({ defaultTitle: attributes.title, @@ -147,7 +157,8 @@ export class NavigationEmbeddable public async reload() { if (this.isDestroyed) return; - await this.initializeSavedLinks(this.getInput()); + // By-reference embeddable panels are reloaded when changed, so update the componentState + this.initializeSavedLinks(); this.render(); } diff --git a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_factory.ts b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_factory.ts index d05ca560e350a..3226833f1f9c8 100644 --- a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_factory.ts +++ b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_factory.ts @@ -7,41 +7,25 @@ */ import { - ACTION_ADD_PANEL, EmbeddableFactory, EmbeddableFactoryDefinition, - EmbeddablePackageState, ErrorEmbeddable, } from '@kbn/embeddable-plugin/public'; import { lazyLoadReduxToolsPackage } from '@kbn/presentation-util-plugin/public'; import { EmbeddablePersistableStateService } from '@kbn/embeddable-plugin/common'; import { DashboardContainer } from '@kbn/dashboard-plugin/public/dashboard_container'; -import { - NavigationEmbeddableByValueInput, - NavigationEmbeddableByReferenceInput, - NavigationEmbeddableInput, -} from './types'; +import { NavigationEmbeddableByReferenceInput, NavigationEmbeddableInput } from './types'; import { APP_ICON, APP_NAME, CONTENT_ID } from '../../common'; import type { NavigationEmbeddable } from './navigation_embeddable'; -import { NAV_VERTICAL_LAYOUT } from '../../common/content_management'; import { getNavigationEmbeddableAttributeService } from '../services/attribute_service'; import { coreServices, untilPluginStartServicesReady } from '../services/kibana_services'; export type NavigationEmbeddableFactory = EmbeddableFactory; -export interface NavigationEmbeddableCreationOptions { - getInitialInput?: () => Partial; - getIncomingEmbeddable?: () => EmbeddablePackageState | undefined; -} - // TODO: Replace string 'OPEN_FLYOUT_ADD_DRILLDOWN' with constant as part of https://github.com/elastic/kibana/issues/154381 -const getDefaultNavigationEmbeddableInput = (): Omit => ({ - attributes: { - title: '', - layout: NAV_VERTICAL_LAYOUT, - }, - disabledActions: [ACTION_ADD_PANEL, 'OPEN_FLYOUT_ADD_DRILLDOWN'], +const getDefaultNavigationEmbeddableInput = (): Partial => ({ + disabledActions: ['OPEN_FLYOUT_ADD_DRILLDOWN'], }); export class NavigationEmbeddableFactoryDefinition diff --git a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_reducers.ts b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_reducers.ts index 29a79c4f6154f..b671c395e061b 100644 --- a/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_reducers.ts +++ b/src/plugins/navigation_embeddable/public/embeddable/navigation_embeddable_reducers.ts @@ -11,6 +11,7 @@ import { WritableDraft } from 'immer/dist/types/types-external'; import { PayloadAction } from '@reduxjs/toolkit'; import { NavigationEmbeddableReduxState } from './types'; +import { NavigationEmbeddableAttributes } from '../../common/content_management'; export const navigationEmbeddableReducers = { /** @@ -24,4 +25,11 @@ export const navigationEmbeddableReducers = { ) => { state.output.loading = action.payload; }, + + setAttributes: ( + state: WritableDraft, + action: PayloadAction + ) => { + state.componentState = { ...action.payload }; + }, }; diff --git a/src/plugins/navigation_embeddable/public/embeddable/types.ts b/src/plugins/navigation_embeddable/public/embeddable/types.ts index 04e79731b6a77..8744dd613c4b5 100644 --- a/src/plugins/navigation_embeddable/public/embeddable/types.ts +++ b/src/plugins/navigation_embeddable/public/embeddable/types.ts @@ -82,10 +82,10 @@ export type NavigationEmbeddableOutput = EmbeddableOutput & { /** * Navigation embeddable redux state */ -// export interface NavigationEmbeddableComponentState {} // TODO: Uncomment this if we end up needing component state +export type NavigationEmbeddableComponentState = NavigationEmbeddableAttributes; export type NavigationEmbeddableReduxState = ReduxEmbeddableState< NavigationEmbeddableInput, NavigationEmbeddableOutput, - {} // We currently don't have any component state - TODO: Replace with `NavigationEmbeddableComponentState` if necessary + NavigationEmbeddableComponentState >;