Skip to content

Commit

Permalink
[Navigation embeddable] Add content management (#160896)
Browse files Browse the repository at this point in the history
Fixes #154362

## Summary

Adds content management to navigation embeddable feature branch.

Allows Links panels to be by-value or by-reference on a Dashboard. The
UX for users to choose to save by-value or by-reference remains to be
finalized and is out of scope for this PR.

---------

Co-authored-by: kibanamachine <[email protected]>
Co-authored-by: Hannah Mudge <[email protected]>
  • Loading branch information
3 people authored Aug 10, 2023
1 parent c7485e6 commit 577134c
Show file tree
Hide file tree
Showing 51 changed files with 1,275 additions and 248 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ export const DEFAULT_INDEX_TYPES_MAP: IndexTypesMap = {
'ml-module',
'ml-trained-model',
'monitoring-telemetry',
'navigation_embeddable',
'osquery-manager-usage-metric',
'osquery-pack',
'osquery-pack-asset',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1504,6 +1504,23 @@ export const INDEX_MAP_BEFORE_SPLIT: IndexMap = {
},
},
},
navigation_embeddable: {
properties: {
id: {
type: 'text',
},
title: {
type: 'text',
},
description: {
type: 'text',
},
links: {
dynamic: false,
properties: {},
},
},
},
'cases-comments': {
dynamic: false,
properties: {
Expand Down
17 changes: 17 additions & 0 deletions packages/kbn-check-mappings-update-cli/current_mappings.json
Original file line number Diff line number Diff line change
Expand Up @@ -1054,6 +1054,23 @@
}
}
},
"navigation_embeddable": {
"properties": {
"id": {
"type": "text"
},
"title": {
"type": "text"
},
"description": {
"type": "text"
},
"links": {
"dynamic": false,
"properties": {}
}
}
},
"lens": {
"properties": {
"title": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ describe('checking migration metadata changes on all registered SO types', () =>
"ml-module": "2225cbb4bd508ea5f69db4b848be9d8a74b60198",
"ml-trained-model": "482195cefd6b04920e539d34d7356d22cb68e4f3",
"monitoring-telemetry": "5d91bf75787d9d4dd2fae954d0b3f76d33d2e559",
"navigation_embeddable": "de71a127ed325261ca6bc926d93c4cd676d17a05",
"observability-onboarding-state": "55b112d6a33fedb7c1e4fec4da768d2bcc5fadc2",
"osquery-manager-usage-metric": "983bcbc3b7dda0aad29b20907db233abba709bcc",
"osquery-pack": "6ab4358ca4304a12dcfc1777c8135b75cffb4397",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ describe('split .kibana index into multiple system indices', () => {
"ml-module",
"ml-trained-model",
"monitoring-telemetry",
"navigation_embeddable",
"observability-onboarding-state",
"osquery-manager-usage-metric",
"osquery-pack",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ import {
} from '@kbn/embeddable-plugin/public';
import { Toast } from '@kbn/core/public';

import { DashboardPanelState } from '../../common';
import { pluginServices } from '../services/plugin_services';
import { dashboardReplacePanelActionStrings } from './_dashboard_actions_strings';
import { DashboardContainer } from '../dashboard_container';
Expand Down Expand Up @@ -58,30 +57,15 @@ export class ReplacePanelFlyout extends React.Component<Props> {

public onReplacePanel = async (savedObjectId: string, type: string, name: string) => {
const { panelToRemove, container } = this.props;
const { w, h, x, y } = (container.getInput().panels[panelToRemove.id] as DashboardPanelState)
.gridData;

const { id } = await container.addNewEmbeddable<SavedObjectEmbeddableInput>(type, {
savedObjectId,
});

const { [panelToRemove.id]: omit, ...panels } = container.getInput().panels;

container.updateInput({
panels: {
...panels,
[id]: {
...panels[id],
gridData: {
...(panels[id] as DashboardPanelState).gridData,
w,
h,
x,
y,
},
} as DashboardPanelState,
const id = await container.replaceEmbeddable<SavedObjectEmbeddableInput>(
panelToRemove.id,
{
savedObjectId,
},
});
type,
true
);

(container as DashboardContainer).setHighlightPanelId(id);
this.showToast(name);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,46 +47,15 @@ export async function replacePanel(
newPanelState: Partial<PanelState>,
generateNewId?: boolean
): Promise<string> {
let panels;
let panelId;

if (generateNewId) {
// replace panel can be called with generateNewId in order to totally destroy and recreate the embeddable
panelId = uuidv4();
panels = { ...this.input.panels };
delete panels[previousPanelState.explicitInput.id];
panels[panelId] = {
...previousPanelState,
...newPanelState,
gridData: {
...previousPanelState.gridData,
i: panelId,
},
explicitInput: {
...newPanelState.explicitInput,
id: panelId,
},
};
} else {
// Because the embeddable type can change, we have to operate at the container level here
panelId = previousPanelState.explicitInput.id;
panels = {
...this.input.panels,
[panelId]: {
...previousPanelState,
...newPanelState,
gridData: {
...previousPanelState.gridData,
},
explicitInput: {
...newPanelState.explicitInput,
id: panelId,
},
},
};
}

await this.updateInput({ panels });
const panelId = await this.replaceEmbeddable(
previousPanelState.explicitInput.id,
{
...newPanelState.explicitInput,
id: previousPanelState.explicitInput.id,
},
newPanelState.type,
generateNewId
);
return panelId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,13 @@ export class EditPanelAction implements Action<ActionContext> {
}

const oldExplicitInput = embeddable.getExplicitInput();
const newExplicitInput = await factory.getExplicitInput(oldExplicitInput, embeddable.parent);
let newExplicitInput: Awaited<ReturnType<typeof factory.getExplicitInput>>;
try {
newExplicitInput = await factory.getExplicitInput(oldExplicitInput, embeddable.parent);
} catch (e) {
// error likely means user canceled editing
return;
}
embeddable.parent?.replaceEmbeddable(embeddable.id, newExplicitInput);
return;
}
Expand Down
38 changes: 25 additions & 13 deletions src/plugins/embeddable/public/lib/containers/container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,12 @@ export abstract class Container<
EEI extends EmbeddableInput = EmbeddableInput,
EEO extends EmbeddableOutput = EmbeddableOutput,
E extends IEmbeddable<EEI, EEO> = IEmbeddable<EEI, EEO>
>(id: string, newExplicitInput: Partial<EEI>, newType?: string) {
>(
id: string,
newExplicitInput: Partial<EEI>,
newType?: string,
generateNewId?: boolean
): Promise<string> {
if (!this.input.panels[id]) {
throw new PanelNotFoundError();
}
Expand All @@ -186,21 +191,28 @@ export abstract class Container<
if (!factory) {
throw new EmbeddableFactoryNotFoundError(newType);
}
this.updateInput({
panels: {
...this.input.panels,
[id]: {
...this.input.panels[id],
explicitInput: { ...newExplicitInput, id },
type: newType,
},
},
} as Partial<TContainerInput>);
} else {
this.updateInputForChild(id, newExplicitInput);
}

const panels = { ...this.input.panels };
const oldPanel = panels[id];

if (generateNewId) {
delete panels[id];
id = uuidv4();
}
this.updateInput({
panels: {
...panels,
[id]: {
...oldPanel,
explicitInput: { ...newExplicitInput, id },
type: newType ?? oldPanel.type,
},
},
} as Partial<TContainerInput>);

await this.untilEmbeddableLoaded<E>(id);
return id;
}

public removeEmbeddable(embeddableId: string) {
Expand Down
5 changes: 3 additions & 2 deletions src/plugins/embeddable/public/lib/containers/i_container.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export interface IContainer<
>(
id: string,
newExplicitInput: Partial<EEI>,
newType?: string
): void;
newType?: string,
generateNewId?: boolean
): Promise<string>;
}
19 changes: 19 additions & 0 deletions src/plugins/navigation_embeddable/common/constants.ts
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 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 or the Server
* Side Public License, v 1.
*/

import { i18n } from '@kbn/i18n';

export const LATEST_VERSION = 1;

export const CONTENT_ID = 'navigation_embeddable';

export const APP_ICON = 'link';

export const APP_NAME = i18n.translate('navigationEmbeddable.visTypeAlias.title', {
defaultMessage: 'Links',
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

import type {
ContentManagementServicesDefinition as ServicesDefinition,
Version,
} from '@kbn/object-versioning';

// We export the versioned service definition from this file and not the barrel to avoid adding
// the schemas in the "public" js bundle

import { serviceDefinition as v1 } from './v1/cm_services';

export const cmServicesDefinition: { [version: Version]: ServicesDefinition } = {
1: v1,
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

export { LATEST_VERSION, CONTENT_ID } from '../constants';

export type { NavigationEmbeddableContentType } from '../types';

export type {
NavigationEmbeddableCrudTypes,
NavigationEmbeddableAttributes,
NavigationEmbeddableItem,
NavigationLinkType,
NavigationEmbeddableLink,
} from './latest';

export { DASHBOARD_LINK_TYPE, EXTERNAL_LINK_TYPE } from './latest';

export * as NavigationEmbeddableV1 from './v1';
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
/*
* 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 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 or the Server
* Side Public License, v 1.
*/

export * from './v1';
Loading

0 comments on commit 577134c

Please sign in to comment.