Add editApp and editPath to embeddable (#64297)
This commit is contained in:
parent
45aa090e99
commit
a32d7b1344
|
@ -275,6 +275,7 @@ class DashboardGridUi extends React.Component<DashboardGridProps, State> {
|
|||
getEmbeddableFactory={this.props.kibana.services.embeddable.getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={this.props.kibana.services.embeddable.getEmbeddableFactories}
|
||||
overlays={this.props.kibana.services.overlays}
|
||||
application={this.props.kibana.services.application}
|
||||
notifications={this.props.kibana.services.notifications}
|
||||
inspector={this.props.kibana.services.inspector}
|
||||
SavedObjectFinder={this.props.kibana.services.SavedObjectFinder}
|
||||
|
|
|
@ -84,6 +84,7 @@ test('DashboardContainer in edit mode shows edit mode actions', async () => {
|
|||
getAllEmbeddableFactories={(() => []) as any}
|
||||
getEmbeddableFactory={(() => null) as any}
|
||||
notifications={{} as any}
|
||||
application={{} as any}
|
||||
overlays={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
|
|
|
@ -41,7 +41,7 @@ class EditableEmbeddable extends Embeddable {
|
|||
}
|
||||
|
||||
test('is compatible when edit url is available, in edit mode and editable', async () => {
|
||||
const action = new EditPanelAction(getFactory);
|
||||
const action = new EditPanelAction(getFactory, {} as any);
|
||||
expect(
|
||||
await action.isCompatible({
|
||||
embeddable: new EditableEmbeddable({ id: '123', viewMode: ViewMode.EDIT }, true),
|
||||
|
@ -50,7 +50,7 @@ test('is compatible when edit url is available, in edit mode and editable', asyn
|
|||
});
|
||||
|
||||
test('getHref returns the edit urls', async () => {
|
||||
const action = new EditPanelAction(getFactory);
|
||||
const action = new EditPanelAction(getFactory, {} as any);
|
||||
expect(action.getHref).toBeDefined();
|
||||
|
||||
if (action.getHref) {
|
||||
|
@ -64,7 +64,7 @@ test('getHref returns the edit urls', async () => {
|
|||
});
|
||||
|
||||
test('is not compatible when edit url is not available', async () => {
|
||||
const action = new EditPanelAction(getFactory);
|
||||
const action = new EditPanelAction(getFactory, {} as any);
|
||||
const embeddable = new ContactCardEmbeddable(
|
||||
{
|
||||
id: '123',
|
||||
|
@ -83,7 +83,7 @@ test('is not compatible when edit url is not available', async () => {
|
|||
});
|
||||
|
||||
test('is not visible when edit url is available but in view mode', async () => {
|
||||
const action = new EditPanelAction(getFactory);
|
||||
const action = new EditPanelAction(getFactory, {} as any);
|
||||
expect(
|
||||
await action.isCompatible({
|
||||
embeddable: new EditableEmbeddable(
|
||||
|
@ -98,7 +98,7 @@ test('is not visible when edit url is available but in view mode', async () => {
|
|||
});
|
||||
|
||||
test('is not compatible when edit url is available, in edit mode, but not editable', async () => {
|
||||
const action = new EditPanelAction(getFactory);
|
||||
const action = new EditPanelAction(getFactory, {} as any);
|
||||
expect(
|
||||
await action.isCompatible({
|
||||
embeddable: new EditableEmbeddable(
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { ApplicationStart } from 'kibana/public';
|
||||
import { Action } from 'src/plugins/ui_actions/public';
|
||||
import { ViewMode } from '../types';
|
||||
import { EmbeddableFactoryNotFoundError } from '../errors';
|
||||
|
@ -35,7 +36,10 @@ export class EditPanelAction implements Action<ActionContext> {
|
|||
public readonly id = ACTION_EDIT_PANEL;
|
||||
public order = 15;
|
||||
|
||||
constructor(private readonly getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory']) {}
|
||||
constructor(
|
||||
private readonly getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'],
|
||||
private readonly application: ApplicationStart
|
||||
) {}
|
||||
|
||||
public getDisplayName({ embeddable }: ActionContext) {
|
||||
const factory = this.getEmbeddableFactory(embeddable.type);
|
||||
|
@ -56,18 +60,35 @@ export class EditPanelAction implements Action<ActionContext> {
|
|||
|
||||
public async isCompatible({ embeddable }: ActionContext) {
|
||||
const canEditEmbeddable = Boolean(
|
||||
embeddable && embeddable.getOutput().editable && embeddable.getOutput().editUrl
|
||||
embeddable &&
|
||||
embeddable.getOutput().editable &&
|
||||
(embeddable.getOutput().editUrl ||
|
||||
(embeddable.getOutput().editApp && embeddable.getOutput().editPath))
|
||||
);
|
||||
const inDashboardEditMode = embeddable.getInput().viewMode === ViewMode.EDIT;
|
||||
return Boolean(canEditEmbeddable && inDashboardEditMode);
|
||||
}
|
||||
|
||||
public async execute(context: ActionContext) {
|
||||
const appTarget = this.getAppTarget(context);
|
||||
|
||||
if (appTarget) {
|
||||
await this.application.navigateToApp(appTarget.app, { path: appTarget.path });
|
||||
return;
|
||||
}
|
||||
|
||||
const href = await this.getHref(context);
|
||||
if (href) {
|
||||
// TODO: when apps start using browser router instead of hash router this has to be fixed
|
||||
// https://github.com/elastic/kibana/issues/58217
|
||||
window.location.href = href;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
public getAppTarget({ embeddable }: ActionContext): { app: string; path: string } | undefined {
|
||||
const app = embeddable ? embeddable.getOutput().editApp : undefined;
|
||||
const path = embeddable ? embeddable.getOutput().editPath : undefined;
|
||||
if (app && path) {
|
||||
return { app, path };
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -66,6 +66,7 @@ test('EmbeddableChildPanel renders an embeddable when it is done loading', async
|
|||
getAllEmbeddableFactories={start.getEmbeddableFactories}
|
||||
getEmbeddableFactory={getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
application={{} as any}
|
||||
overlays={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
|
@ -105,6 +106,7 @@ test(`EmbeddableChildPanel renders an error message if the factory doesn't exist
|
|||
getEmbeddableFactory={(() => undefined) as any}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
/>
|
||||
|
|
|
@ -40,6 +40,7 @@ export interface EmbeddableChildPanelProps {
|
|||
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
|
||||
overlays: CoreStart['overlays'];
|
||||
notifications: CoreStart['notifications'];
|
||||
application: CoreStart['application'];
|
||||
inspector: InspectorStartContract;
|
||||
SavedObjectFinder: React.ComponentType<any>;
|
||||
}
|
||||
|
@ -101,6 +102,7 @@ export class EmbeddableChildPanel extends React.Component<EmbeddableChildPanelPr
|
|||
getEmbeddableFactory={this.props.getEmbeddableFactory}
|
||||
getAllEmbeddableFactories={this.props.getAllEmbeddableFactories}
|
||||
overlays={this.props.overlays}
|
||||
application={this.props.application}
|
||||
notifications={this.props.notifications}
|
||||
inspector={this.props.inspector}
|
||||
SavedObjectFinder={this.props.SavedObjectFinder}
|
||||
|
|
|
@ -55,6 +55,8 @@ export interface EmbeddableInput {
|
|||
|
||||
export interface EmbeddableOutput {
|
||||
editUrl?: string;
|
||||
editApp?: string;
|
||||
editPath?: string;
|
||||
defaultTitle?: string;
|
||||
title?: string;
|
||||
editable?: boolean;
|
||||
|
|
|
@ -159,6 +159,7 @@ test('HelloWorldContainer in view mode hides edit mode actions', async () => {
|
|||
getAllEmbeddableFactories={start.getEmbeddableFactories}
|
||||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
application={{} as any}
|
||||
overlays={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
|
@ -198,6 +199,7 @@ const renderInEditModeAndOpenContextMenu = async (
|
|||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
/>
|
||||
|
@ -296,6 +298,7 @@ test('HelloWorldContainer in edit mode shows edit mode actions', async () => {
|
|||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
/>
|
||||
|
@ -358,6 +361,7 @@ test('Updates when hidePanelTitles is toggled', async () => {
|
|||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
/>
|
||||
|
@ -410,6 +414,7 @@ test('Check when hide header option is false', async () => {
|
|||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
hideHeader={false}
|
||||
|
@ -447,6 +452,7 @@ test('Check when hide header option is true', async () => {
|
|||
getEmbeddableFactory={start.getEmbeddableFactory}
|
||||
notifications={{} as any}
|
||||
overlays={{} as any}
|
||||
application={{} as any}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={() => null}
|
||||
hideHeader={true}
|
||||
|
|
|
@ -45,6 +45,7 @@ interface Props {
|
|||
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
|
||||
overlays: CoreStart['overlays'];
|
||||
notifications: CoreStart['notifications'];
|
||||
application: CoreStart['application'];
|
||||
inspector: InspectorStartContract;
|
||||
SavedObjectFinder: React.ComponentType<any>;
|
||||
hideHeader?: boolean;
|
||||
|
@ -243,7 +244,7 @@ export class EmbeddablePanel extends React.Component<Props, State> {
|
|||
),
|
||||
new InspectPanelAction(this.props.inspector),
|
||||
new RemovePanelAction(),
|
||||
new EditPanelAction(this.props.getEmbeddableFactory),
|
||||
new EditPanelAction(this.props.getEmbeddableFactory, this.props.application),
|
||||
];
|
||||
|
||||
const sorted = actions
|
||||
|
|
|
@ -49,6 +49,7 @@ interface HelloWorldContainerOptions {
|
|||
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
|
||||
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
|
||||
overlays: CoreStart['overlays'];
|
||||
application: CoreStart['application'];
|
||||
notifications: CoreStart['notifications'];
|
||||
inspector: InspectorStartContract;
|
||||
SavedObjectFinder: React.ComponentType<any>;
|
||||
|
@ -81,6 +82,7 @@ export class HelloWorldContainer extends Container<InheritedInput, HelloWorldCon
|
|||
getAllEmbeddableFactories={this.options.getAllEmbeddableFactories}
|
||||
getEmbeddableFactory={this.options.getEmbeddableFactory}
|
||||
overlays={this.options.overlays}
|
||||
application={this.options.application}
|
||||
notifications={this.options.notifications}
|
||||
inspector={this.options.inspector}
|
||||
SavedObjectFinder={this.options.SavedObjectFinder}
|
||||
|
|
|
@ -32,6 +32,7 @@ interface Props {
|
|||
getEmbeddableFactory: EmbeddableStart['getEmbeddableFactory'];
|
||||
getAllEmbeddableFactories: EmbeddableStart['getEmbeddableFactories'];
|
||||
overlays: CoreStart['overlays'];
|
||||
application: CoreStart['application'];
|
||||
notifications: CoreStart['notifications'];
|
||||
inspector: InspectorStartContract;
|
||||
SavedObjectFinder: React.ComponentType<any>;
|
||||
|
@ -112,6 +113,7 @@ export class HelloWorldContainerComponent extends Component<Props, State> {
|
|||
getAllEmbeddableFactories={this.props.getAllEmbeddableFactories}
|
||||
overlays={this.props.overlays}
|
||||
notifications={this.props.notifications}
|
||||
application={this.props.application}
|
||||
inspector={this.props.inspector}
|
||||
SavedObjectFinder={this.props.SavedObjectFinder}
|
||||
/>
|
||||
|
|
|
@ -118,6 +118,7 @@ export class EmbeddablePublicPlugin implements Plugin<EmbeddableSetup, Embeddabl
|
|||
getAllEmbeddableFactories={this.getEmbeddableFactories}
|
||||
overlays={core.overlays}
|
||||
notifications={core.notifications}
|
||||
application={core.application}
|
||||
inspector={inspector}
|
||||
SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)}
|
||||
/>
|
||||
|
|
|
@ -110,6 +110,7 @@ test('ApplyFilterAction is incompatible if the root container does not accept a
|
|||
getAllEmbeddableFactories: api.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -145,6 +146,7 @@ test('trying to execute on incompatible context throws an error ', async () => {
|
|||
getAllEmbeddableFactories: api.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ async function creatHelloWorldContainerAndEmbeddable(
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
});
|
||||
|
@ -147,6 +148,7 @@ test('Container.removeEmbeddable removes and cleans up', async done => {
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -327,6 +329,7 @@ test(`Container updates its state when a child's input is updated`, async done =
|
|||
getEmbeddableFactory: start.getEmbeddableFactory,
|
||||
notifications: coreStart.notifications,
|
||||
overlays: coreStart.overlays,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
});
|
||||
|
@ -584,6 +587,7 @@ test('Container changes made directly after adding a new embeddable are propagat
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -708,6 +712,7 @@ test('untilEmbeddableLoaded() throws an error if there is no such child panel in
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -742,6 +747,7 @@ test('untilEmbeddableLoaded() resolves if child is loaded in the container', asy
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -781,6 +787,7 @@ test('untilEmbeddableLoaded resolves with undefined if child is subsequently rem
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -821,6 +828,7 @@ test('adding a panel then subsequently removing it before its loaded removes the
|
|||
getAllEmbeddableFactories: start.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
|
|
@ -63,6 +63,7 @@ beforeEach(async () => {
|
|||
getAllEmbeddableFactories: api.getEmbeddableFactories,
|
||||
overlays: coreStart.overlays,
|
||||
notifications: coreStart.notifications,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
|
|
@ -88,6 +88,7 @@ test('Explicit embeddable input mapped to undefined with no inherited value will
|
|||
getEmbeddableFactory: start.getEmbeddableFactory,
|
||||
notifications: coreStart.notifications,
|
||||
overlays: coreStart.overlays,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
@ -136,6 +137,7 @@ test('Explicit input tests in async situations', (done: () => void) => {
|
|||
getEmbeddableFactory: start.getEmbeddableFactory,
|
||||
notifications: coreStart.notifications,
|
||||
overlays: coreStart.overlays,
|
||||
application: coreStart.application,
|
||||
inspector: {} as any,
|
||||
SavedObjectFinder: () => null,
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => {
|
|||
getAllEmbeddableFactories={plugins.embeddable.getEmbeddableFactories}
|
||||
notifications={core.notifications}
|
||||
overlays={core.overlays}
|
||||
application={core.application}
|
||||
inspector={plugins.inspector}
|
||||
SavedObjectFinder={getSavedObjectFinder(core.savedObjects, core.uiSettings)}
|
||||
/>
|
||||
|
|
|
@ -208,6 +208,7 @@ export const EmbeddedMapComponent = ({
|
|||
notifications={services.notifications}
|
||||
overlays={services.overlays}
|
||||
inspector={services.inspector}
|
||||
application={services.application}
|
||||
SavedObjectFinder={getSavedObjectFinder(services.savedObjects, services.uiSettings)}
|
||||
/>
|
||||
) : !isLoading && isIndexError ? (
|
||||
|
|
Loading…
Reference in a new issue