Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
60 commits
Select commit Hold shift + click to select a range
455077d
[Dashboards as Code] Stub out embeddable content management registry …
nickpeihl May 27, 2025
9952b0b
Add embeddabEmbeddableStart to dashboard transforms, move inject/extr…
Zacqary May 27, 2025
3f0dac2
Add embeddable cmd to panel transforms
Zacqary May 27, 2025
0a42de7
Update example embeddables with CMDs
Zacqary May 27, 2025
9d77ba5
Make book SavedObject schema absolutely irredeemably stupid-looking
Zacqary May 27, 2025
3f48423
Defer panel migration for eEmbeddableStart availability
Zacqary May 28, 2025
4bcf0ae
[Dashboards as Code] Register example book saved object and content m…
nickpeihl May 29, 2025
3579f91
Remove unneeded flow call
Zacqary May 30, 2025
5da8aa6
[Dashboards as Code] Provide embeddable service for migration (#222059)
nickpeihl May 30, 2025
bc81f03
Merge branch 'dashboardApi/embeddableIntegration' of https://github.c…
Zacqary Jun 2, 2025
e8be0c2
Save and load book embeddables from SavedBookStorage
Zacqary Jun 2, 2025
4086c00
Make saved books visible in management
Zacqary Jun 2, 2025
27e09c7
Add book embeddable to Add from Library
Zacqary Jun 2, 2025
b63b91e
Add sequelTo saved object referenceobject to book example
Zacqary Jun 3, 2025
713412c
Remove attriubutes and references from item schemas
Zacqary Jun 3, 2025
cd19731
Fix panel in transform
Zacqary Jun 3, 2025
7546c3b
Deprectate references in SerializedPanelState
Zacqary Jun 4, 2025
1e43ff0
Fix deprecation comment
Zacqary Jun 4, 2025
43b7349
Merge remote-tracking branch 'upstream/main' into dashboardApi/embedd…
nickpeihl Jun 5, 2025
7b1cedb
[CI] Auto-commit changed files from 'node scripts/notice'
kibanamachine Jun 5, 2025
7d60fb7
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jun 5, 2025
d2295ae
[Dashboards as Code][Embeddable API Integration] Make EmbeddableConte…
nickpeihl Jun 6, 2025
b355942
Make extractDashboardState async and pull from CM registry
Zacqary Jun 6, 2025
06daa5e
Fix running savedObjectToItem on pre-8.17 panels
Zacqary Jun 9, 2025
6df5880
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jun 9, 2025
fb5773b
Fix typecheck and i18n
Zacqary Jun 9, 2025
f4146b4
Merge branch 'dashboardApi/embeddableIntegration' of https://github.c…
Zacqary Jun 9, 2025
7f43799
Update unit tests for async functions
nickpeihl Jun 10, 2025
f95fda8
Fix unused ts-expect-error
Zacqary Jun 10, 2025
dd2d7d3
Merge branch 'dashboardApi/embeddableIntegration' of https://github.c…
Zacqary Jun 10, 2025
f00b67e
Remove @ts-expect-errors
Zacqary Jun 10, 2025
78ac7a8
Merge remote-tracking branch 'upstream/main' into dashboardApi/embedd…
Zacqary Jun 10, 2025
9b30b2b
Fix mock typechecks
Zacqary Jun 10, 2025
8adc5f4
Merge branch 'main' into dashboardApi/embeddableIntegration
Zacqary Jun 11, 2025
3421df5
Decouple EmbeddableContentManagementRegistry from EmbeddablePersistab…
nickpeihl Jun 11, 2025
cd8e69c
[Dashboards as Code][Embeddable API Integration] Make registry synchr…
Zacqary Jun 12, 2025
cc3a64f
Fix typecheck and lastSavedState example
Zacqary Jun 12, 2025
a4cef41
Revert ts-expect-errors and SavedObjectMigrationParams type, add expe…
Zacqary Jun 12, 2025
fc8f6af
Revert ts-expect-error removal
Zacqary Jun 13, 2025
a3f0df6
Revert "Revert ts-expect-error removal"
Zacqary Jun 13, 2025
56c2a5d
Revert ts-expect-error removal
Zacqary Jun 13, 2025
6b5a09f
Fix typecheck
Zacqary Jun 13, 2025
548e4ed
Fix binding error in registry
Zacqary Jun 13, 2025
0aaa869
Remove console.error
Zacqary Jun 13, 2025
7485faa
Update ts-expect-error comment with github issue link
Zacqary Jun 16, 2025
895cab4
Fix security jest test
Zacqary Jun 16, 2025
9904656
Merge remote-tracking branch 'upstream/main' into dashboardApi/embedd…
Zacqary Jun 16, 2025
8bebf31
Fix bad merge
Zacqary Jun 16, 2025
394030a
Merge remote-tracking branch 'upstream/main' into dashboardApi/embedd…
Zacqary Jun 17, 2025
9cc0438
[CI] Auto-commit changed files from 'node scripts/eslint --no-cache -…
kibanamachine Jun 17, 2025
451ae2b
Fix merge
Zacqary Jun 17, 2025
c95efa7
Merge branch 'dashboardApi/embeddableIntegration' of https://github.c…
Zacqary Jun 17, 2025
d88d146
Fix 8.17 panel extraction
Zacqary Jun 17, 2025
f1214a6
Fix unsaved changes flag tripping from panel reference injection
Zacqary Jun 18, 2025
bc4c5e9
Remove embeddable.inject test from dashboard transform
Zacqary Jun 20, 2025
e9b3286
Merge remote-tracking branch 'upstream/main' into dashboardApi/embedd…
Zacqary Jun 20, 2025
799a7f6
Remove inject tests and fix async error test in panelOutTransforms
Zacqary Jun 20, 2025
57a32c0
Merge branch 'main' into dashboardApi/embeddableIntegration
elasticmachine Jun 23, 2025
43a8497
Merge branch 'main' into dashboardApi/embeddableIntegration
nreese Jun 25, 2025
6415b9c
Merge branch 'main' into dashboardApi/embeddableIntegration
elasticmachine Jun 27, 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
@@ -0,0 +1,19 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { EmbeddableContentManagementDefinition } from '@kbn/embeddable-plugin/common';
import { bookAttributesDefinition } from './schema';

export const bookCmDefinitions: EmbeddableContentManagementDefinition = {
id: 'book',
versions: {
1: bookAttributesDefinition,
},
latestVersion: 1,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export const BOOK_LATEST_VERSION = 1;

export const BOOK_CONTENT_ID = 'book';

export const SEQUEL_TO_REF_NAME = 'kibanaSavedObjectMeta.sequelToBook.id';
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { bookAttributesDefinition, bookItemSchema, type BookItem } from './schema';
export { BOOK_CONTENT_ID, BOOK_LATEST_VERSION } from './constants';
export { itemToSavedObject, savedObjectToItem } from './transforms';
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { TypeOf, schema } from '@kbn/config-schema';
import type { VersionableEmbeddableObject } from '@kbn/embeddable-plugin/common';
import type { SavedBookAttributes } from '../../../../server/types';
import { itemToSavedObject, savedObjectToItem } from './transforms';

export const bookItemSchema = schema.object({
bookTitle: schema.string(),
author: schema.string(),
pages: schema.number(),
synopsis: schema.maybe(schema.string()),
published: schema.maybe(schema.number()),
sequelTo: schema.maybe(schema.string()),
});

export type BookItem = TypeOf<typeof bookItemSchema>;

export const bookAttributesDefinition: VersionableEmbeddableObject<SavedBookAttributes, BookItem> =
{
itemToSavedObject,
savedObjectToItem,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { itemToSavedObject } from './item_to_saved_object';
export { savedObjectToItem } from './saved_object_to_item';
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { SavedObjectAttributesWithReferences } from '@kbn/embeddable-plugin/common/types';
import type { SavedObjectReference } from '@kbn/core/server';
import { Mutable } from 'utility-types';
import {
BOOK_SAVED_OBJECT_TYPE,
type SavedBookAttributes,
} from '../../../../../server/book/saved_object';
import { SEQUEL_TO_REF_NAME } from '../constants';
import { BookItem } from '../schema';

const extractReferences = (attributes: BookItem) => {
const references: SavedObjectReference[] = [];
const extractedRefNames: Mutable<Partial<SavedBookAttributes['metadata']>> = {};
if (attributes.sequelTo) {
extractedRefNames.sequelToBookRefName = SEQUEL_TO_REF_NAME;
references.push({
name: SEQUEL_TO_REF_NAME,
type: BOOK_SAVED_OBJECT_TYPE,
id: attributes.sequelTo,
});
}
return { references, extractedRefNames };
};

export const itemToSavedObject = (
attributes: BookItem
): SavedObjectAttributesWithReferences<SavedBookAttributes> => {
const { references, extractedRefNames } = extractReferences(attributes);
return {
attributes: {
bookTitleAsArray: [...attributes.bookTitle],
metadata: {
numbers: {
numberOfPages: attributes.pages,
publicationYear: attributes.published ?? undefined,
},
text: {
authorName: attributes.author,
bookSynopsis: attributes.synopsis,
},
...extractedRefNames,
},
// Generate a string of random letters and numbers to demonstrate simplifying a savedObject
uselessGarbage: Array.from(Array(10), () => Math.random().toString(36).substring(2)).join(''),
},
references,
};
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { SavedObjectAttributesWithReferences } from '@kbn/embeddable-plugin/common/types';
import type { SavedObjectReference } from '@kbn/core/server';
import { Mutable } from 'utility-types';
import type { SavedBookAttributes } from '../../../../../server/book/saved_object';
import { BookItem } from '../schema';

const injectReferences = (attributes: SavedBookAttributes, references: SavedObjectReference[]) => {
const injectedParams: Mutable<Partial<BookItem>> = {};
if (attributes.metadata.sequelToBookRefName) {
const sequelId = references.find((r) => r.name === attributes.metadata.sequelToBookRefName)?.id;
if (sequelId) injectedParams.sequelTo = sequelId;
}
return injectedParams;
};

// 8.x used this SavedObject schema to store Book embeddables in URLs
// It is NOT recommended to radically change SavedObject schemas other than adding additional optional fields,
// but legacy URL handling is a special case
interface BookSavedURLObjectAttributes {
bookTitle: string;
bookSynopsis?: string;
numberOfPages: number;
authorName: string;
}
const isUrlObject = (so: unknown): so is BookSavedURLObjectAttributes =>
!!(so as BookSavedURLObjectAttributes).bookTitle;

const savedURLObjectToItem = ({
bookTitle,
bookSynopsis,
numberOfPages,
authorName,
}: BookSavedURLObjectAttributes): BookItem => ({
bookTitle,
synopsis: bookSynopsis,
author: authorName,
pages: numberOfPages,
});

export const savedObjectToItem = (
so: SavedObjectAttributesWithReferences<SavedBookAttributes> | BookSavedURLObjectAttributes
): BookItem =>
isUrlObject(so)
? savedURLObjectToItem(so)
: {
bookTitle: so.attributes.bookTitleAsArray.join(''),
author: so.attributes.metadata.text.authorName,
pages: so.attributes.metadata.numbers.numberOfPages,
synopsis: so.attributes.metadata.text.bookSynopsis,
published: so.attributes.metadata.numbers.publicationYear ?? undefined,
...injectReferences(so.attributes, so.references),
};
11 changes: 11 additions & 0 deletions examples/embeddable_examples/common/field_list/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export const FIELD_LIST_DATA_VIEW_REF_NAME = 'field_list_data_view_id';
export const FIELD_LIST_ID = 'field_list';
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import { EmbeddableContentManagementDefinition } from '@kbn/embeddable-plugin/common';
import { fieldListAttributesDefinition as fieldListAttributesDefinitionV1 } from './schema/v1';
import { fieldListAttributesDefinition as fieldListAttributesDefinitionV2 } from './schema/v2';
import { FIELD_LIST_ID } from '../constants';

/**
* In version 1 of the field list, the client-side embeddable was expected to inject and extract references.
* So the `itemToSavedObject` and `savedObjectToItem` methods were identity functions.
* In version 2 of the field list, the server handles data views references.
* So the `itemToSavedObject` and `savedObjectToItem` methods perform reference extraction and injection
* and the embeddable client does not need to know about references.
*/
export const fieldListCmDefinitions: EmbeddableContentManagementDefinition = {
id: FIELD_LIST_ID,
versions: {
1: fieldListAttributesDefinitionV1,
2: fieldListAttributesDefinitionV2,
},
latestVersion: 2,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { fieldListAttributesDefinition } from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { VersionableEmbeddableObject } from '@kbn/embeddable-plugin/common';
import type { SavedFieldListAttributes } from '../../../../../server/types';
import type { FieldListAttributes } from '../../../../../server/field_list/content_management/schema/v1';

export const fieldListAttributesDefinition: VersionableEmbeddableObject<
SavedFieldListAttributes,
FieldListAttributes
> = {
itemToSavedObject: (item) => ({ attributes: item, references: [] }),
savedObjectToItem: ({ attributes }) => attributes,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

export { fieldListAttributesDefinition } from './v2';
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the "Elastic License
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
* Public License v 1"; you may not use this file except in compliance with, at
* your election, the "Elastic License 2.0", the "GNU Affero General Public
* License v3.0 only", or the "Server Side Public License, v 1".
*/

import type { VersionableEmbeddableObject } from '@kbn/embeddable-plugin/common';
import { DATA_VIEW_SAVED_OBJECT_TYPE } from '@kbn/data-views-plugin/common';
import type { SavedFieldListAttributes } from '../../../../../server/types';
import type { FieldListAttributes } from '../../../../../server/field_list/content_management/schema/v2';
import { FIELD_LIST_DATA_VIEW_REF_NAME } from '../../../constants';

export const fieldListAttributesDefinition: VersionableEmbeddableObject<
SavedFieldListAttributes,
FieldListAttributes
> = {
itemToSavedObject: (item) => {
const { selectedFieldNames, dataViewId } = item;
const references = [];
if (dataViewId) {
// inject data view id as a reference
references.push({
name: FIELD_LIST_DATA_VIEW_REF_NAME,
type: DATA_VIEW_SAVED_OBJECT_TYPE,
id: dataViewId,
});
}
return {
attributes: {
// don't store the dataViewId, it's in the references
selectedFieldNames,
},
references,
};
},
savedObjectToItem: ({ attributes, references }) => {
const { selectedFieldNames } = attributes;
// inject data view id from references
const dataViewRef = references.find((ref) => ref.name === FIELD_LIST_DATA_VIEW_REF_NAME);
return {
selectedFieldNames,
dataViewId: dataViewRef?.id,
};
},
};
11 changes: 9 additions & 2 deletions examples/embeddable_examples/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
"description": "Example app that shows how to register custom embeddables",
"plugin": {
"id": "embeddableExamples",
"server": false,
"server": true,
"browser": true,
"requiredPlugins": [
"contentManagement",
"dataViews",
"embeddable",
"uiActions",
Expand All @@ -18,6 +19,12 @@
"developerExamples",
"dataViewFieldEditor"
],
"requiredBundles": ["dashboard", "presentationUtil", "kibanaUtils", "kibanaReact"]
"requiredBundles": [
"dashboard",
"presentationUtil",
"kibanaUtils",
"kibanaReact",
"savedObjectsFinder"
]
}
}
6 changes: 4 additions & 2 deletions examples/embeddable_examples/public/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,12 @@ const App = ({
{
id: 'presentationContainer',
title: 'Create a dashboard like experience with embeddables',
component: <PresentationContainerExample uiActions={deps.uiActions} />,
component: (
<PresentationContainerExample uiActions={deps.uiActions} embeddable={deps.embeddable} />
),
},
];
}, [deps.uiActions]);
}, [deps.uiActions, deps.embeddable]);

const routes = useMemo(() => {
return pages.map((page) => (
Expand Down
Loading