Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Serialized state only] Update Library Transforms and Duplicate #206140

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
2b7503f
Make library transforms and clone use serialized state only
ThomThomson Jan 9, 2025
10a67ae
Merge remote-tracking branch 'upstream/main' into serializedStateOnly…
ThomThomson Jan 9, 2025
f48077c
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 9, 2025
2b5f4d1
import type from presentation containers
ThomThomson Jan 9, 2025
a9dc283
move has_serializable_state to presentation publishing. Update maps t…
ThomThomson Jan 9, 2025
4f3d3de
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jan 9, 2025
c47056b
fix imports
ThomThomson Jan 10, 2025
0afc6bb
Merge remote-tracking branch 'upstream/main' into serializedStateOnly…
ThomThomson Jan 10, 2025
83e68d3
Merge remote-tracking branch 'refs/remotes/origin/serializedStateOnly…
ThomThomson Jan 10, 2025
e7e1741
update lens mock
ThomThomson Jan 10, 2025
c7772a7
Update clone panel test
ThomThomson Jan 13, 2025
e9c65e3
Merge remote-tracking branch 'upstream/main' into serializedStateOnly…
ThomThomson Jan 13, 2025
196150c
updated links jest tests
ThomThomson Jan 13, 2025
d0f56c2
update a11y test types
ThomThomson Jan 13, 2025
e6a7f65
Merge remote-tracking branch 'upstream/main' into serializedStateOnly…
ThomThomson Jan 15, 2025
097e488
Make Visualize Embeddable properly implement HasLibraryTransforms
ThomThomson Jan 15, 2025
9a0956b
Merge remote-tracking branch 'upstream/main' into serializedStateOnly…
ThomThomson Jan 15, 2025
c52be6e
fix pushing references
ThomThomson Jan 16, 2025
615ee5b
simplify ref count check
ThomThomson Jan 16, 2025
7e59d72
Merge branch 'main' into serializedStateOnly/libraryTransforms
elasticmachine Jan 20, 2025
938981d
Merge branch 'main' into serializedStateOnly/libraryTransforms
elasticmachine Jan 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { SerializedPanelState } from '@kbn/presentation-containers';
import type { SerializedPanelState } from '@kbn/presentation-publishing';
import type { ControlGroupSerializedState } from '@kbn/controls-plugin/common';
import {
OPTIONS_LIST_CONTROL,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { v4 as generateId } from 'uuid';
import { TimeRange } from '@kbn/es-query';
import {
PanelPackage,
apiHasSerializableState,
childrenUnsavedChanges$,
combineCompatibleChildrenApis,
} from '@kbn/presentation-containers';
Expand All @@ -21,6 +20,7 @@ import {
PublishesDataLoading,
PublishingSubject,
ViewMode,
apiHasSerializableState,
apiPublishesDataLoading,
apiPublishesUnsavedChanges,
} from '@kbn/presentation-publishing';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ import {
HasSerializedChildState,
HasRuntimeChildState,
PresentationContainer,
SerializedPanelState,
HasSaveNotification,
} from '@kbn/presentation-containers';
import {
HasExecutionContext,
PublishesDataLoading,
PublishesTimeRange,
PublishesUnsavedChanges,
SerializedPanelState,
PublishesViewMode,
} from '@kbn/presentation-publishing';
import { PublishesReload } from '@kbn/presentation-publishing/interfaces/fetch/publishes_reload';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { SerializedPanelState } from '@kbn/presentation-containers';
import { SerializedPanelState } from '@kbn/presentation-publishing';
import { BookSerializedState } from '../../react_embeddables/saved_book/types';

const SAVED_STATE_SESSION_STORAGE_KEY =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,7 @@ import { CoreStart } from '@kbn/core-lifecycle-browser';
import { OverlayRef } from '@kbn/core-mount-utils-browser';
import { i18n } from '@kbn/i18n';
import { tracksOverlays } from '@kbn/presentation-containers';
import {
apiHasInPlaceLibraryTransforms,
apiHasUniqueId,
useBatchedOptionalPublishingSubjects,
} from '@kbn/presentation-publishing';
import { apiHasUniqueId, useBatchedOptionalPublishingSubjects } from '@kbn/presentation-publishing';
import { toMountPoint } from '@kbn/react-kibana-mount';
import React, { useState } from 'react';
import { serializeBookAttributes } from './book_state';
Expand Down Expand Up @@ -74,7 +70,7 @@ export const openSavedBookEditor = ({
onSubmit={async (addToLibrary: boolean) => {
const savedBookId = addToLibrary
? await saveBookAttributes(
apiHasInPlaceLibraryTransforms(api) ? api.libraryId$.value : undefined,
api?.getSavedBookId(),
serializeBookAttributes(attributesManager)
)
: undefined;
Expand Down Expand Up @@ -114,15 +110,13 @@ export const SavedBookEditor = ({
onCancel: () => void;
api?: BookApi;
}) => {
const [libraryId, authorName, synopsis, bookTitle, numberOfPages] =
useBatchedOptionalPublishingSubjects(
api?.libraryId$,
attributesManager.authorName,
attributesManager.bookSynopsis,
attributesManager.bookTitle,
attributesManager.numberOfPages
);
const [addToLibrary, setAddToLibrary] = useState(Boolean(libraryId));
const [authorName, synopsis, bookTitle, numberOfPages] = useBatchedOptionalPublishingSubjects(
attributesManager.authorName,
attributesManager.bookSynopsis,
attributesManager.bookTitle,
attributesManager.numberOfPages
);
const [addToLibrary, setAddToLibrary] = useState(Boolean(api?.getSavedBookId()));
const [saving, setSaving] = useState(false);

return (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ import { ReactEmbeddableFactory } from '@kbn/embeddable-plugin/public';
import { i18n } from '@kbn/i18n';
import {
apiHasParentApi,
getUnchangingComparator,
initializeTitles,
SerializedTitles,
SerializedPanelState,
useBatchedPublishingSubjects,
} from '@kbn/presentation-publishing';
import React from 'react';
import { BehaviorSubject } from 'rxjs';
import { PresentationContainer } from '@kbn/presentation-containers';
import { serializeBookAttributes, stateManagerFromAttributes } from './book_state';
import { SAVED_BOOK_ID } from './constants';
Expand Down Expand Up @@ -82,7 +83,24 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => {
buildEmbeddable: async (state, buildApi) => {
const { titlesApi, titleComparators, serializeTitles } = initializeTitles(state);
const bookAttributesManager = stateManagerFromAttributes(state);
const savedBookId$ = new BehaviorSubject(state.savedBookId);
const isByReference = Boolean(state.savedBookId);

const serializeBook = (byReference: boolean, newId?: string) => {
if (byReference) {
// if this book is currently by reference, we serialize the reference only.
const bookByReferenceState: BookByReferenceSerializedState = {
savedBookId: newId ?? state.savedBookId!,
...serializeTitles(),
};
return { rawState: bookByReferenceState };
}
// if this book is currently by value, we serialize the entire state.
const bookByValueState: BookByValueSerializedState = {
attributes: serializeBookAttributes(bookAttributesManager),
...serializeTitles(),
};
return { rawState: bookByValueState };
};

const api = buildApi(
{
Expand All @@ -95,55 +113,44 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => {
core,
api,
}).then((result) => {
savedBookId$.next(result.savedBookId);
const nextIsByReference = Boolean(result.savedBookId);

// if the by reference state has changed during this edit, reinitialize the panel.
if (nextIsByReference !== isByReference) {
api.parentApi?.replacePanel<BookSerializedState>(api.uuid, {
serializedState: serializeBook(nextIsByReference, result.savedBookId),
panelType: api.type,
});
}
});
},
isEditingEnabled: () => true,
getTypeDisplayName: () =>
i18n.translate('embeddableExamples.savedbook.editBook.displayName', {
defaultMessage: 'book',
}),
serializeState: () => {
if (!Boolean(savedBookId$.value)) {
// if this book is currently by value, we serialize the entire state.
const bookByValueState: BookByValueSerializedState = {
attributes: serializeBookAttributes(bookAttributesManager),
...serializeTitles(),
};
return { rawState: bookByValueState };
}

// if this book is currently by reference, we serialize the reference only.
const bookByReferenceState: BookByReferenceSerializedState = {
savedBookId: savedBookId$.value!,
...serializeTitles(),
};
return { rawState: bookByReferenceState };
},
serializeState: () => serializeBook(isByReference),

// in place library transforms
libraryId$: savedBookId$,
// library transforms
getSavedBookId: () => state.savedBookId,
saveToLibrary: async (newTitle: string) => {
bookAttributesManager.bookTitle.next(newTitle);
const newId = await saveBookAttributes(
undefined,
serializeBookAttributes(bookAttributesManager)
);
savedBookId$.next(newId);
return newId;
},
checkForDuplicateTitle: async (title) => {},
unlinkFromLibrary: () => {
savedBookId$.next(undefined);
},
getByValueRuntimeSnapshot: () => {
const snapshot = api.snapshotRuntimeState();
delete snapshot.savedBookId;
return snapshot;
},
getSerializedStateByValue: () =>
serializeBook(false) as SerializedPanelState<BookByValueSerializedState>,
getSerializedStateByReference: (newId) =>
serializeBook(true, newId) as SerializedPanelState<BookByReferenceSerializedState>,
canLinkToLibrary: async () => !isByReference,
canUnlinkFromLibrary: async () => isByReference,
},
{
savedBookId: [savedBookId$, (val) => savedBookId$.next(val)],
savedBookId: getUnchangingComparator(), // saved book id will not change over the lifetime of the embeddable.
...bookAttributesManager.comparators,
...titleComparators,
}
Expand All @@ -156,14 +163,12 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => {
return {
api,
Component: () => {
const [authorName, numberOfPages, savedBookId, bookTitle, synopsis] =
useBatchedPublishingSubjects(
bookAttributesManager.authorName,
bookAttributesManager.numberOfPages,
savedBookId$,
bookAttributesManager.bookTitle,
bookAttributesManager.bookSynopsis
);
const [authorName, numberOfPages, bookTitle, synopsis] = useBatchedPublishingSubjects(
bookAttributesManager.authorName,
bookAttributesManager.numberOfPages,
bookAttributesManager.bookTitle,
bookAttributesManager.bookSynopsis
);
const { euiTheme } = useEuiTheme();

return (
Expand All @@ -177,15 +182,15 @@ export const getSavedBookEmbeddableFactory = (core: CoreStart) => {
size="s"
color={'warning'}
title={
savedBookId
isByReference
? i18n.translate('embeddableExamples.savedBook.libraryCallout', {
defaultMessage: 'Saved in library',
})
: i18n.translate('embeddableExamples.savedBook.noLibraryCallout', {
defaultMessage: 'Not saved in library',
})
}
iconType={savedBookId ? 'folderCheck' : 'folderClosed'}
iconType={isByReference ? 'folderCheck' : 'folderClosed'}
/>
)}
<div
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
import { DefaultEmbeddableApi } from '@kbn/embeddable-plugin/public';
import {
HasEditCapabilities,
HasInPlaceLibraryTransforms,
HasLibraryTransforms,
SerializedTitles,
StateComparators,
} from '@kbn/presentation-publishing';
Expand All @@ -35,6 +35,10 @@ export interface BookByReferenceSerializedState {
savedBookId: string;
}

export interface HasSavedBookId {
getSavedBookId: () => string | undefined;
}

export type BookSerializedState = SerializedTitles &
(BookByValueSerializedState | BookByReferenceSerializedState);

Expand All @@ -48,4 +52,5 @@ export interface BookRuntimeState

export type BookApi = DefaultEmbeddableApi<BookSerializedState, BookRuntimeState> &
HasEditCapabilities &
HasInPlaceLibraryTransforms<BookRuntimeState>;
HasLibraryTransforms<BookByReferenceSerializedState, BookByValueSerializedState> &
HasSavedBookId;
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type {
SearchEmbeddableRuntimeState,
SearchEmbeddableApi,
} from '@kbn/discover-plugin/public';
import { SerializedPanelState } from '@kbn/presentation-containers';
import { SerializedPanelState } from '@kbn/presentation-publishing';
import { css } from '@emotion/react';
import { SavedSearchComponentProps } from '../types';
import { SavedSearchComponentErrorContent } from './error';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
"@kbn/es-query",
"@kbn/data-plugin",
"@kbn/discover-plugin",
"@kbn/presentation-containers",
"@kbn/i18n",
"@kbn/presentation-publishing",
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,4 @@ export {
type PresentationContainer,
} from './interfaces/presentation_container';
export { apiPublishesSettings, type PublishesSettings } from './interfaces/publishes_settings';
export {
apiHasSerializableState,
type HasSerializableState,
type HasSnapshottableState,
type SerializedPanelState,
} from './interfaces/serialized_state';
export { tracksOverlays, type TracksOverlays } from './interfaces/tracks_overlays';
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,17 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { SerializedPanelState } from './serialized_state';
import { SerializedPanelState } from '@kbn/presentation-publishing';

export interface HasSerializedChildState<SerializedState extends object = object> {
getSerializedStateForChild: (
childId: string
) => SerializedPanelState<SerializedState> | undefined;
}

/**
* @deprecated Use `HasSerializedChildState` instead. All interactions between the container and the child should use the serialized state.
*/
export interface HasRuntimeChildState<RuntimeState extends object = object> {
getRuntimeStateForChild: (childId: string) => Partial<RuntimeState> | undefined;
}
Expand All @@ -24,7 +27,9 @@ export const apiHasSerializedChildState = <SerializedState extends object = obje
): api is HasSerializedChildState<SerializedState> => {
return Boolean(api && (api as HasSerializedChildState).getSerializedStateForChild);
};

/**
* @deprecated Use `HasSerializedChildState` instead. All interactions between the container and the child should use the serialized state.
*/
export const apiHasRuntimeChildState = <RuntimeState extends object = object>(
api: unknown
): api is HasRuntimeChildState<RuntimeState> => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,30 @@
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { apiHasParentApi, apiHasUniqueId, PublishingSubject } from '@kbn/presentation-publishing';
import {
apiHasParentApi,
apiHasUniqueId,
PublishingSubject,
SerializedPanelState,
} from '@kbn/presentation-publishing';
import { BehaviorSubject, combineLatest, isObservable, map, Observable, of, switchMap } from 'rxjs';
import { apiCanAddNewPanel, CanAddNewPanel } from './can_add_new_panel';

export interface PanelPackage<SerializedState extends object = object> {
export interface PanelPackage<
SerializedStateType extends object = object,
RuntimeStateType extends object = object
> {
panelType: string;
initialState?: SerializedState;

/**
* The serialized state of this panel.
*/
serializedState?: SerializedPanelState<SerializedStateType>;

/**
* The runtime state of this panel. @deprecated Use `serializedState` instead.
*/
initialState?: RuntimeStateType;
}

export interface PresentationContainer extends CanAddNewPanel {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ import {
PublishingSubject,
runComparators,
StateComparators,
HasSnapshottableState,
} from '@kbn/presentation-publishing';
import { HasSnapshottableState } from '../serialized_state';
import { apiHasSaveNotification } from '../has_save_notification';

export const COMPARATOR_SUBJECTS_DEBOUNCE = 100;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,5 @@
"kbn_references": [
"@kbn/presentation-publishing",
"@kbn/core-mount-utils-browser",
"@kbn/content-management-utils",
]
}
Loading
Loading