Skip to content

Commit

Permalink
[Exploratory view] Allow ability add extra actions in lens embeddable (
Browse files Browse the repository at this point in the history
  • Loading branch information
shahzad31 authored Jan 28, 2022
1 parent 9f6c781 commit 5b8af6c
Show file tree
Hide file tree
Showing 20 changed files with 401 additions and 44 deletions.
53 changes: 51 additions & 2 deletions x-pack/examples/embedded_lens_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
} from '../../../plugins/lens/public';

import { ViewMode } from '../../../../src/plugins/embeddable/public';
import { ActionExecutionContext } from '../../../../src/plugins/ui_actions/public';

// Generate a Lens state based on some app-specific input parameters.
// `TypedLensByValueInput` can be used for type-safety - it uses the same interfaces as Lens-internal code.
Expand Down Expand Up @@ -126,6 +127,9 @@ export const App = (props: {
to: 'now',
});

const [enableExtraAction, setEnableExtraAction] = useState(false);
const [enableDefaultAction, setEnableDefaultAction] = useState(false);

const LensComponent = props.plugins.lens.EmbeddableComponent;
const LensSaveModalComponent = props.plugins.lens.SaveModalComponent;

Expand Down Expand Up @@ -153,7 +157,7 @@ export const App = (props: {
configuration and navigate to a prefilled editor.
</p>

<EuiFlexGroup>
<EuiFlexGroup wrap>
<EuiFlexItem grow={false}>
<EuiButton
data-test-subj="lns-example-change-color"
Expand Down Expand Up @@ -238,10 +242,34 @@ export const App = (props: {
Change time range
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
aria-label="Enable extra action"
data-test-subj="lns-example-extra-action"
isDisabled={!attributes}
onClick={() => {
setEnableExtraAction((prevState) => !prevState);
}}
>
{enableExtraAction ? 'Disable extra action' : 'Enable extra action'}
</EuiButton>
</EuiFlexItem>
<EuiFlexItem grow={false}>
<EuiButton
aria-label="Enable default actions"
data-test-subj="lns-example-default-action"
isDisabled={!attributes}
onClick={() => {
setEnableDefaultAction((prevState) => !prevState);
}}
>
{enableDefaultAction ? 'Disable default action' : 'Enable default action'}
</EuiButton>
</EuiFlexItem>
</EuiFlexGroup>
<LensComponent
id=""
withActions
withDefaultActions={enableDefaultAction}
style={{ height: 500 }}
timeRange={time}
attributes={attributes}
Expand All @@ -261,6 +289,27 @@ export const App = (props: {
// call back event for on table row click event
}}
viewMode={ViewMode.VIEW}
extraActions={
enableExtraAction
? [
{
id: 'testAction',
type: 'link',
getIconType: () => 'save',
async isCompatible(
context: ActionExecutionContext<object>
): Promise<boolean> {
return true;
},
execute: async (context: ActionExecutionContext<object>) => {
alert('I am an extra action');
return;
},
getDisplayName: () => 'Extra action',
},
]
: undefined
}
/>
{isSaveModalVisible && (
<LensSaveModalComponent
Expand Down
7 changes: 4 additions & 3 deletions x-pack/examples/exploratory_view_example/kibana.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,14 @@
"server": false,
"ui": true,
"requiredPlugins": [
"observability",
"cases",
"data",
"developerExamples",
"embeddable",
"developerExamples"
"observability"
],
"optionalPlugins": [],
"requiredBundles": [],
"requiredBundles": ["kibanaReact"],
"owner": {
"name": "`Synthetics team`",
"githubTeam": "uptime"
Expand Down
1 change: 1 addition & 0 deletions x-pack/examples/exploratory_view_example/public/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ export const App = (props: {
attributes={seriesList}
reportType="kpi-over-time"
title={'Monitor response duration'}
withActions={['save', 'explore']}
/>
</EuiPageContentBody>
</EuiPageContent>
Expand Down
17 changes: 12 additions & 5 deletions x-pack/examples/exploratory_view_example/public/mount.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,12 @@

import * as React from 'react';
import { render, unmountComponentAtNode } from 'react-dom';
import { CoreSetup, AppMountParameters } from 'kibana/public';
import { CoreSetup, AppMountParameters, APP_WRAPPER_CLASS } from '../../../../src/core/public';
import { StartDependencies } from './plugin';

import {
KibanaContextProvider,
RedirectAppLinks,
} from '../../../../src/plugins/kibana_react/public';
export const mount =
(coreSetup: CoreSetup<StartDependencies>) =>
async ({ element }: AppMountParameters) => {
Expand All @@ -26,9 +29,13 @@ export const mount =
const i18nCore = core.i18n;

const reactElement = (
<i18nCore.Context>
<App {...deps} defaultIndexPattern={defaultIndexPattern} />
</i18nCore.Context>
<KibanaContextProvider services={{ ...coreSetup, ...core, ...plugins }}>
<i18nCore.Context>
<RedirectAppLinks application={core.application} className={APP_WRAPPER_CLASS}>
<App {...deps} defaultIndexPattern={defaultIndexPattern} />
</RedirectAppLinks>
</i18nCore.Context>
</KibanaContextProvider>
);
render(reactElement, element);
return () => unmountComponentAtNode(element);
Expand Down
23 changes: 19 additions & 4 deletions x-pack/plugins/lens/public/embeddable/embeddable_component.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

import React, { FC, useEffect } from 'react';
import type { CoreStart, ThemeServiceStart } from 'kibana/public';
import type { UiActionsStart } from 'src/plugins/ui_actions/public';
import type { Action, UiActionsStart } from 'src/plugins/ui_actions/public';
import type { Start as InspectorStartContract } from 'src/plugins/inspector/public';
import { EuiLoadingChart } from '@elastic/eui';
import {
Expand Down Expand Up @@ -52,7 +52,8 @@ export type TypedLensByValueInput = Omit<LensByValueInput, 'attributes'> & {
};

export type EmbeddableComponentProps = (TypedLensByValueInput | LensByReferenceInput) & {
withActions?: boolean;
withDefaultActions?: boolean;
extraActions?: Action[];
};

interface PluginsStartDependencies {
Expand All @@ -67,7 +68,9 @@ export function getEmbeddableComponent(core: CoreStart, plugins: PluginsStartDep
const factory = embeddableStart.getEmbeddableFactory('lens')!;
const input = { ...props };
const [embeddable, loading, error] = useEmbeddableFactory({ factory, input });
const hasActions = props.withActions === true;
const hasActions =
Boolean(props.withDefaultActions) || (props.extraActions && props.extraActions?.length > 0);

const theme = core.theme;

if (loading) {
Expand All @@ -83,6 +86,8 @@ export function getEmbeddableComponent(core: CoreStart, plugins: PluginsStartDep
actionPredicate={() => hasActions}
input={input}
theme={theme}
extraActions={props.extraActions}
withDefaultActions={props.withDefaultActions}
/>
);
}
Expand All @@ -98,6 +103,8 @@ interface EmbeddablePanelWrapperProps {
actionPredicate: (id: string) => boolean;
input: EmbeddableComponentProps;
theme: ThemeServiceStart;
extraActions?: Action[];
withDefaultActions?: boolean;
}

const EmbeddablePanelWrapper: FC<EmbeddablePanelWrapperProps> = ({
Expand All @@ -107,6 +114,8 @@ const EmbeddablePanelWrapper: FC<EmbeddablePanelWrapperProps> = ({
inspector,
input,
theme,
extraActions,
withDefaultActions,
}) => {
useEffect(() => {
embeddable.updateInput(input);
Expand All @@ -116,7 +125,13 @@ const EmbeddablePanelWrapper: FC<EmbeddablePanelWrapperProps> = ({
<EmbeddablePanel
hideHeader={false}
embeddable={embeddable as IEmbeddable<EmbeddableInput, EmbeddableOutput>}
getActions={uiActions.getTriggerCompatibleActions}
getActions={async (triggerId, context) => {
const actions = withDefaultActions
? await uiActions.getTriggerCompatibleActions(triggerId, context)
: [];

return [...(extraActions ?? []), ...actions];
}}
inspector={inspector}
actionPredicate={actionPredicate}
showShadow={false}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -783,7 +783,7 @@ export class LensAttributes {
};
}

getJSON(refresh?: number): TypedLensByValueInput['attributes'] {
getJSON(): TypedLensByValueInput['attributes'] {
const uniqueIndexPatternsIds = Array.from(
new Set([...this.layerConfigs.map(({ indexPattern }) => indexPattern.id)])
);
Expand All @@ -792,7 +792,7 @@ export class LensAttributes {

return {
title: 'Prefilled from exploratory view app',
description: String(refresh),
description: '',
visualizationType: 'lnsXY',
references: [
...uniqueIndexPatternsIds.map((patternId) => ({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/
export const sampleAttribute = {
description: 'undefined',
description: '',
references: [
{
id: 'apm-*',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/
export const sampleAttributeCoreWebVital = {
description: 'undefined',
description: '',
references: [
{
id: 'apm-*',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
* 2.0.
*/
export const sampleAttributeKpi = {
description: 'undefined',
description: '',
references: [
{
id: 'apm-*',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,15 +49,30 @@ export function convertToShortUrl(series: SeriesUrl) {
};
}

export function createExploratoryViewRoutePath({
reportType,
allSeries,
}: {
reportType: ReportViewType;
allSeries: AllSeries;
}) {
const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series));

return `/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
allShortSeries as unknown as RisonValue
)}`;
}

export function createExploratoryViewUrl(
{ reportType, allSeries }: { reportType: ReportViewType; allSeries: AllSeries },
baseHref = ''
baseHref = '',
appId = 'observability'
) {
const allShortSeries: AllShortSeries = allSeries.map((series) => convertToShortUrl(series));

return (
baseHref +
`/app/observability/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
`/app/${appId}/exploratory-view/#?reportType=${reportType}&sr=${rison.encode(
allShortSeries as unknown as RisonValue
)}`
);
Expand Down
Loading

0 comments on commit 5b8af6c

Please sign in to comment.