Skip to content

Commit

Permalink
[8.10] [Dashboard] Get panel description from the embeddable method (#…
Browse files Browse the repository at this point in the history
…166825) (#166897)

# Backport

This will backport the following commits from `main` to `8.10`:
- [[Dashboard] Get panel description from the embeddable method
(#166825)](#166825)

<!--- Backport version: 8.9.7 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Nick
Peihl","email":"[email protected]"},"sourceCommit":{"committedDate":"2023-09-20T21:56:54Z","message":"[Dashboard]
Get panel description from the embeddable method (#166825)\n\nFixes
#166773 \r\n\r\n## Summary\r\n\r\nFixes a bug where panels are not
showing descriptions from library\r\nitems.\r\n\r\nChanges the panel to
use the `embeddable.getDescription` method for\r\nretrieving the
description. This is necessary since by-reference panels\r\ncan store
descriptions in the saved object. `getDescription` will check\r\nfor a
description in the saved object attributes, but the panel\r\ndescription
will still take precedence. This is very similar to how we\r\nget the
panel
title.","sha":"26893e2e363ad875fea5506a050b4729de20394f","branchLabelMapping":{"^v8.11.0$":"main","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["Feature:Embedding","release_note:fix","Team:Presentation","v8.11.0","v8.10.3"],"number":166825,"url":"https://github.com/elastic/kibana/pull/166825","mergeCommit":{"message":"[Dashboard]
Get panel description from the embeddable method (#166825)\n\nFixes
#166773 \r\n\r\n## Summary\r\n\r\nFixes a bug where panels are not
showing descriptions from library\r\nitems.\r\n\r\nChanges the panel to
use the `embeddable.getDescription` method for\r\nretrieving the
description. This is necessary since by-reference panels\r\ncan store
descriptions in the saved object. `getDescription` will check\r\nfor a
description in the saved object attributes, but the panel\r\ndescription
will still take precedence. This is very similar to how we\r\nget the
panel
title.","sha":"26893e2e363ad875fea5506a050b4729de20394f"}},"sourceBranch":"main","suggestedTargetBranches":["8.10"],"targetPullRequestStates":[{"branch":"main","label":"v8.11.0","labelRegex":"^v8.11.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/166825","number":166825,"mergeCommit":{"message":"[Dashboard]
Get panel description from the embeddable method (#166825)\n\nFixes
#166773 \r\n\r\n## Summary\r\n\r\nFixes a bug where panels are not
showing descriptions from library\r\nitems.\r\n\r\nChanges the panel to
use the `embeddable.getDescription` method for\r\nretrieving the
description. This is necessary since by-reference panels\r\ncan store
descriptions in the saved object. `getDescription` will check\r\nfor a
description in the saved object attributes, but the panel\r\ndescription
will still take precedence. This is very similar to how we\r\nget the
panel
title.","sha":"26893e2e363ad875fea5506a050b4729de20394f"}},{"branch":"8.10","label":"v8.10.3","labelRegex":"^v(\\d+).(\\d+).\\d+$","isSourceBranch":false,"state":"NOT_CREATED"}]}]
BACKPORT-->

Co-authored-by: Nick Peihl <[email protected]>
  • Loading branch information
kibanamachine and nickpeihl authored Sep 22, 2023
1 parent 5e728ad commit 093f590
Show file tree
Hide file tree
Showing 5 changed files with 121 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ import { EmbeddablePanel } from './embeddable_panel';
import { core, inspector } from '../kibana_services';
import { CONTEXT_MENU_TRIGGER, ViewMode } from '..';
import { UnwrappedEmbeddablePanelProps } from './types';
import {
DESCRIPTIVE_CONTACT_CARD_EMBEDDABLE,
DescriptiveContactCardEmbeddableFactory,
} from '../lib/test_samples/embeddables/contact_card/descriptive_contact_card_embeddable_factory';

const actionRegistry = new Map<string, Action>();
const triggerRegistry = new Map<string, Trigger>();
Expand All @@ -46,11 +50,15 @@ const embeddableReactFactory = new ContactCardEmbeddableReactFactory(
(() => null) as any,
{} as any
);
const descriptiveEmbeddableFactory = new DescriptiveContactCardEmbeddableFactory(
(() => null) as any
);

actionRegistry.set(editModeAction.id, new ActionInternal(editModeAction));
triggerRegistry.set(trigger.id, trigger);
setup.registerEmbeddableFactory(embeddableFactory.type, embeddableFactory);
setup.registerEmbeddableFactory(embeddableReactFactory.type, embeddableReactFactory);
setup.registerEmbeddableFactory(descriptiveEmbeddableFactory.type, descriptiveEmbeddableFactory);

const start = doStart();
const getEmbeddableFactory = start.getEmbeddableFactory;
Expand All @@ -69,7 +77,11 @@ const renderEmbeddableInPanel = async (
return wrapper!;
};

const setupContainerAndEmbeddable = async (viewMode?: ViewMode, hidePanelTitles?: boolean) => {
const setupContainerAndEmbeddable = async (
embeddableType: string,
viewMode: ViewMode = ViewMode.VIEW,
hidePanelTitles?: boolean
) => {
const container = new HelloWorldContainer(
{ id: '123', panels: {}, viewMode: viewMode ?? ViewMode.VIEW, hidePanelTitles },
{
Expand All @@ -81,7 +93,7 @@ const setupContainerAndEmbeddable = async (viewMode?: ViewMode, hidePanelTitles?
ContactCardEmbeddableInput,
ContactCardEmbeddableOutput,
ContactCardEmbeddable
>(CONTACT_CARD_EMBEDDABLE, {
>(embeddableType, {
firstName: 'Jack',
lastName: 'Orange',
});
Expand Down Expand Up @@ -250,7 +262,7 @@ describe('Error states', () => {
});

test('Render method is called on Embeddable', async () => {
const { embeddable } = await setupContainerAndEmbeddable();
const { embeddable } = await setupContainerAndEmbeddable(CONTACT_CARD_EMBEDDABLE);
jest.spyOn(embeddable, 'render');
await renderEmbeddableInPanel({ embeddable });
expect(embeddable.render).toHaveBeenCalledTimes(1);
Expand Down Expand Up @@ -379,7 +391,7 @@ test('Notifications are not shown when hideNotifications is true', async () => {
});

test('Edit mode actions are hidden if parent is in view mode', async () => {
const { embeddable } = await setupContainerAndEmbeddable();
const { embeddable } = await setupContainerAndEmbeddable(CONTACT_CARD_EMBEDDABLE);

const component = await renderEmbeddableInPanel({ embeddable });

Expand All @@ -395,7 +407,7 @@ test('Edit mode actions are hidden if parent is in view mode', async () => {
});

test('Edit mode actions are shown in edit mode', async () => {
const { container, embeddable } = await setupContainerAndEmbeddable();
const { container, embeddable } = await setupContainerAndEmbeddable(CONTACT_CARD_EMBEDDABLE);

const component = await renderEmbeddableInPanel({ embeddable });

Expand Down Expand Up @@ -442,7 +454,11 @@ test('Edit mode actions are shown in edit mode', async () => {
});

test('Panel title customize link does not exist in view mode', async () => {
const { embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, false);
const { embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
false
);

const component = await renderEmbeddableInPanel({ embeddable });

Expand All @@ -454,7 +470,11 @@ test('Runs customize panel action on title click when in edit mode', async () =>
// spy on core openFlyout to check that the flyout is opened correctly.
core.overlays.openFlyout = jest.fn();

const { embeddable } = await setupContainerAndEmbeddable(ViewMode.EDIT, false);
const { embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.EDIT,
false
);

const component = await renderEmbeddableInPanel({ embeddable });

Expand All @@ -472,7 +492,16 @@ test('Runs customize panel action on title click when in edit mode', async () =>
});

test('Updates when hidePanelTitles is toggled', async () => {
const { container, embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, false);
const { container, embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
false
);
/**
* panel title will always show if a description is set so we explictily set the panel
* description so the embeddable description is not used
*/
embeddable.updateInput({ description: '' });
const component = await renderEmbeddableInPanel({ embeddable });

await component.update();
Expand All @@ -499,7 +528,11 @@ test('Updates when hidePanelTitles is toggled', async () => {
});

test('Respects options from SelfStyledEmbeddable', async () => {
const { container, embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, false);
const { container, embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
false
);

const selfStyledEmbeddable = embeddablePluginMock.mockSelfStyledEmbeddable(embeddable, {
hideTitle: true,
Expand All @@ -514,8 +547,24 @@ test('Respects options from SelfStyledEmbeddable', async () => {
expect(title.length).toBe(0);
});

test('Shows icon in panel title when the embeddable has a description', async () => {
const { embeddable } = await setupContainerAndEmbeddable(
DESCRIPTIVE_CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
false
);
const component = await renderEmbeddableInPanel({ embeddable });

const descriptionIcon = findTestSubject(component, 'embeddablePanelTitleDescriptionIcon');
expect(descriptionIcon.length).toBe(1);
});

test('Does not hide header when parent hide header option is false', async () => {
const { embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, false);
const { embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
false
);

const component = await renderEmbeddableInPanel({ embeddable });

Expand All @@ -524,7 +573,11 @@ test('Does not hide header when parent hide header option is false', async () =>
});

test('Hides title when parent hide header option is true', async () => {
const { embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, true);
const { embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
true
);

const component = await renderEmbeddableInPanel({ embeddable });

Expand All @@ -535,7 +588,11 @@ test('Hides title when parent hide header option is true', async () => {
test('Should work in minimal way rendering only the inspector action', async () => {
inspector.isAvailable = jest.fn(() => true);

const { embeddable } = await setupContainerAndEmbeddable(ViewMode.VIEW, true);
const { embeddable } = await setupContainerAndEmbeddable(
CONTACT_CARD_EMBEDDABLE,
ViewMode.VIEW,
true
);

const component = await renderEmbeddableInPanel({ embeddable });

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,8 @@ export const EmbeddablePanelHeader = ({
);

const title = embeddable.getTitle();
const description = embeddable.getDescription();
const viewMode = useSelectFromEmbeddableInput('viewMode', embeddable);
const description = useSelectFromEmbeddableInput('description', embeddable);
const hidePanelTitle = useSelectFromEmbeddableInput('hidePanelTitles', embeddable);
const parentHidePanelTitle = useSelectFromEmbeddableInput('hidePanelTitles', embeddable.parent);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,12 @@ export const EmbeddablePanelTitle = ({
anchorClassName="embPanel__titleTooltipAnchor"
>
<span className="embPanel__titleInner">
{titleComponent} <EuiIcon type="iInCircle" color="subdued" />
{titleComponent}{' '}
<EuiIcon
type="iInCircle"
color="subdued"
data-test-subj="embeddablePanelTitleDescriptionIcon"
/>
</span>
</EuiToolTip>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ export interface ContactCardEmbeddableOutput extends EmbeddableOutput {

export interface ContactCardEmbeddableOptions {
execAction: UiActionsStart['executeTriggerActions'];
outputOverrides?: Partial<ContactCardEmbeddableOutput>;
}

function getFullName(input: ContactCardEmbeddableInput) {
Expand Down Expand Up @@ -56,6 +57,7 @@ export class ContactCardEmbeddable extends Embeddable<
fullName: getFullName(initialInput),
originalLastName: initialInput.lastName,
defaultTitle: `Hello ${getFullName(initialInput)}`,
...options.outputOverrides,
},
parent
);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
* 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 { UiActionsStart } from '@kbn/ui-actions-plugin/public';

import { Container, EmbeddableFactoryDefinition } from '../../..';
import { ContactCardEmbeddable, ContactCardEmbeddableInput } from './contact_card_embeddable';

export const DESCRIPTIVE_CONTACT_CARD_EMBEDDABLE = 'DESCRIPTIVE_CONTACT_CARD_EMBEDDABLE';

export class DescriptiveContactCardEmbeddableFactory
implements EmbeddableFactoryDefinition<ContactCardEmbeddableInput>
{
public readonly type = DESCRIPTIVE_CONTACT_CARD_EMBEDDABLE;

constructor(protected readonly execTrigger: UiActionsStart['executeTriggerActions']) {}

public async isEditable() {
return true;
}

public getDisplayName() {
return 'descriptive contact card';
}

public create = async (initialInput: ContactCardEmbeddableInput, parent?: Container) => {
return new ContactCardEmbeddable(
initialInput,
{
execAction: this.execTrigger,
outputOverrides: {
defaultDescription: 'This is a family friend',
},
},
parent
);
};
}

0 comments on commit 093f590

Please sign in to comment.