Skip to content

Commit

Permalink
[Canvas] Add Lens embeddables (#57499)
Browse files Browse the repository at this point in the history
* Added lens embeddables to embed flyout

Fixed import

embedded panel styles (#58654)

Merging to WIP draft branch

* Added i18n strings for savedLens

* Added tests for lens embeddables

* Updated tests

* Updated tests

* Added style overrides for lens table

* DDisables triggers on lens emebeddable

* Updated test

* Sets embeddable view mode according to app state

* Fix embeddable component

* Removed embeddable view mode logic

* Removed unused import
  • Loading branch information
cqliu1 authored Mar 19, 2020
1 parent fcf4396 commit 3bd3364
Show file tree
Hide file tree
Showing 15 changed files with 282 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,16 @@
// @ts-ignore
import { MAP_SAVED_OBJECT_TYPE } from '../../../maps/common/constants';
import { VISUALIZE_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/visualizations/public';
import { LENS_EMBEDDABLE_TYPE } from '../../../../../plugins/lens/common/constants';
import { SEARCH_EMBEDDABLE_TYPE } from '../../../../../../src/legacy/core_plugins/kibana/public/discover/np_ready/embeddable/constants';

export const EmbeddableTypes: { map: string; search: string; visualization: string } = {
export const EmbeddableTypes: {
lens: string;
map: string;
search: string;
visualization: string;
} = {
lens: LENS_EMBEDDABLE_TYPE,
map: MAP_SAVED_OBJECT_TYPE,
search: SEARCH_EMBEDDABLE_TYPE,
visualization: VISUALIZE_EMBEDDABLE_TYPE,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { rounddate } from './rounddate';
import { rowCount } from './rowCount';
import { repeatImage } from './repeatImage';
import { revealImage } from './revealImage';
import { savedLens } from './saved_lens';
import { savedMap } from './saved_map';
import { savedSearch } from './saved_search';
import { savedVisualization } from './saved_visualization';
Expand Down Expand Up @@ -109,6 +110,7 @@ export const functions = [
revealImage,
rounddate,
rowCount,
savedLens,
savedMap,
savedSearch,
savedVisualization,
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;
* you may not use this file except in compliance with the Elastic License.
*/
jest.mock('ui/new_platform');
import { savedLens } from './saved_lens';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';

const filterContext = {
and: [
{ and: [], value: 'filter-value', column: 'filter-column', type: 'exactly' },
{
and: [],
column: 'time-column',
type: 'time',
from: '2019-06-04T04:00:00.000Z',
to: '2019-06-05T04:00:00.000Z',
},
],
};

describe('savedLens', () => {
const fn = savedLens().fn;
const args = {
id: 'some-id',
title: null,
timerange: null,
};

it('accepts null context', () => {
const expression = fn(null, args, {} as any);

expect(expression.input.filters).toEqual([]);
});

it('accepts filter context', () => {
const expression = fn(filterContext, args, {} as any);
const embeddableFilters = getQueryFilters(filterContext.and);

expect(expression.input.filters).toEqual(embeddableFilters);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
import { TimeRange } from 'src/plugins/data/public';
import { EmbeddableInput } from 'src/legacy/core_plugins/embeddable_api/public/np_ready/public';
import { getQueryFilters } from '../../../public/lib/build_embeddable_filters';
import { Filter, TimeRange as TimeRangeArg } from '../../../types';
import {
EmbeddableTypes,
EmbeddableExpressionType,
EmbeddableExpression,
} from '../../expression_types';
import { getFunctionHelp } from '../../../i18n';
import { Filter as DataFilter } from '../../../../../../../src/plugins/data/public';

interface Arguments {
id: string;
title: string | null;
timerange: TimeRangeArg | null;
}

export type SavedLensInput = EmbeddableInput & {
id: string;
timeRange?: TimeRange;
filters: DataFilter[];
};

const defaultTimeRange = {
from: 'now-15m',
to: 'now',
};

type Return = EmbeddableExpression<SavedLensInput>;

export function savedLens(): ExpressionFunctionDefinition<
'savedLens',
Filter | null,
Arguments,
Return
> {
const { help, args: argHelp } = getFunctionHelp().savedLens;
return {
name: 'savedLens',
help,
args: {
id: {
types: ['string'],
required: false,
help: argHelp.id,
},
timerange: {
types: ['timerange'],
help: argHelp.timerange,
required: false,
},
title: {
types: ['string'],
help: argHelp.title,
required: false,
},
},
type: EmbeddableExpressionType,
fn: (context, args) => {
const filters = context ? context.and : [];

return {
type: EmbeddableExpressionType,
input: {
id: args.id,
filters: getQueryFilters(filters),
timeRange: args.timerange || defaultTimeRange,
title: args.title ? args.title : undefined,
disableTriggers: true,
},
embeddableType: EmbeddableTypes.lens,
};
},
};
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
.canvasEmbeddable {
.embPanel {
border: none;
background: none;

.embPanel__title {
margin-bottom: $euiSizeXS;
}

.embPanel__optionsMenuButton {
border-radius: $euiBorderRadius;
}

.canvas-isFullscreen & {
.embPanel__optionsMenuButton {
opacity: 0;
}

&:focus .embPanel__optionsMenuButton,
&:hover .embPanel__optionsMenuButton {
opacity: 1;
}
}
}

.euiTable {
background: none;
}

.lnsExpressionRenderer {
@include euiScrollBar;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@ import { start } from '../../../../../../../src/legacy/core_plugins/embeddable_a
import { EmbeddableExpression } from '../../expression_types/embeddable';
import { RendererStrings } from '../../../i18n';
import { getSavedObjectFinder } from '../../../../../../../src/plugins/saved_objects/public';

const { embeddable: strings } = RendererStrings;
import { embeddableInputToExpression } from './embeddable_input_to_expression';
import { EmbeddableInput } from '../../expression_types';
import { RendererHandlers } from '../../../types';
import { CANVAS_EMBEDDABLE_CLASSNAME } from '../../../common/lib';

const { embeddable: strings } = RendererStrings;

const embeddablesRegistry: {
[key: string]: IEmbeddable;
Expand All @@ -31,7 +32,7 @@ const embeddablesRegistry: {
const renderEmbeddable = (embeddableObject: IEmbeddable, domNode: HTMLElement) => {
return (
<div
className="embeddable"
className={CANVAS_EMBEDDABLE_CLASSNAME}
style={{ width: domNode.offsetWidth, height: domNode.offsetHeight, cursor: 'auto' }}
>
<I18nContext>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
jest.mock('ui/new_platform');
import { embeddableInputToExpression } from './embeddable_input_to_expression';
import { SavedMapInput } from '../../functions/common/saved_map';
import { SavedLensInput } from '../../functions/common/saved_lens';
import { EmbeddableTypes } from '../../expression_types';
import { fromExpression, Ast } from '@kbn/interpreter/common';

const baseSavedMapInput = {
const baseEmbeddableInput = {
id: 'embeddableId',
filters: [],
};

const baseSavedMapInput = {
...baseEmbeddableInput,
isLayerTOCOpen: false,
refreshConfig: {
isPaused: true,
Expand Down Expand Up @@ -73,4 +78,45 @@ describe('input to expression', () => {
expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to);
});
});

describe('Lens Embeddable', () => {
it('converts to a savedLens expression', () => {
const input: SavedLensInput = {
...baseEmbeddableInput,
};

const expression = embeddableInputToExpression(input, EmbeddableTypes.lens);
const ast = fromExpression(expression);

expect(ast.type).toBe('expression');
expect(ast.chain[0].function).toBe('savedLens');

expect(ast.chain[0].arguments.id).toStrictEqual([input.id]);

expect(ast.chain[0].arguments).not.toHaveProperty('title');
expect(ast.chain[0].arguments).not.toHaveProperty('timerange');
});

it('includes optional input values', () => {
const input: SavedLensInput = {
...baseEmbeddableInput,
title: 'title',
timeRange: {
from: 'now-1h',
to: 'now',
},
};

const expression = embeddableInputToExpression(input, EmbeddableTypes.map);
const ast = fromExpression(expression);

expect(ast.chain[0].arguments).toHaveProperty('title', [input.title]);
expect(ast.chain[0].arguments).toHaveProperty('timerange');

const timerangeExpression = ast.chain[0].arguments.timerange[0] as Ast;
expect(timerangeExpression.chain[0].function).toBe('timerange');
expect(timerangeExpression.chain[0].arguments.from[0]).toEqual(input.timeRange?.from);
expect(timerangeExpression.chain[0].arguments.to[0]).toEqual(input.timeRange?.to);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import { EmbeddableTypes, EmbeddableInput } from '../../expression_types';
import { SavedMapInput } from '../../functions/common/saved_map';
import { SavedLensInput } from '../../functions/common/saved_lens';

/*
Take the input from an embeddable and the type of embeddable and convert it into an expression
Expand Down Expand Up @@ -46,5 +47,23 @@ export function embeddableInputToExpression(
}
}

if (embeddableType === EmbeddableTypes.lens) {
const lensInput = input as SavedLensInput;

expressionParts.push('savedLens');

expressionParts.push(`id="${input.id}"`);

if (input.title) {
expressionParts.push(`title="${input.title}"`);
}

if (lensInput.timeRange) {
expressionParts.push(
`timerange={timerange from="${lensInput.timeRange.from}" to="${lensInput.timeRange.to}"}`
);
}
}

return expressionParts.join(' ');
}
1 change: 1 addition & 0 deletions x-pack/legacy/plugins/canvas/common/lib/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,3 +39,4 @@ export const API_ROUTE_SHAREABLE_BASE = '/public/canvas';
export const API_ROUTE_SHAREABLE_ZIP = '/public/canvas/zip';
export const API_ROUTE_SHAREABLE_RUNTIME = '/public/canvas/runtime';
export const API_ROUTE_SHAREABLE_RUNTIME_DOWNLOAD = `/public/canvas/${SHAREABLE_RUNTIME_NAME}.js`;
export const CANVAS_EMBEDDABLE_CLASSNAME = `canvasEmbeddable`;
27 changes: 27 additions & 0 deletions x-pack/legacy/plugins/canvas/i18n/functions/dict/saved_lens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/

import { i18n } from '@kbn/i18n';
import { savedLens } from '../../../canvas_plugin_src/functions/common/saved_lens';
import { FunctionHelp } from '../function_help';
import { FunctionFactory } from '../../../types';

export const help: FunctionHelp<FunctionFactory<typeof savedLens>> = {
help: i18n.translate('xpack.canvas.functions.savedLensHelpText', {
defaultMessage: `Returns an embeddable for a saved lens object`,
}),
args: {
id: i18n.translate('xpack.canvas.functions.savedLens.args.idHelpText', {
defaultMessage: `The ID of the Saved Lens Object`,
}),
timerange: i18n.translate('xpack.canvas.functions.savedLens.args.timerangeHelpText', {
defaultMessage: `The timerange of data that should be included`,
}),
title: i18n.translate('xpack.canvas.functions.savedLens.args.titleHelpText', {
defaultMessage: `The title for the lens emebeddable`,
}),
},
};
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/canvas/i18n/functions/function_help.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ import { help as replace } from './dict/replace';
import { help as revealImage } from './dict/reveal_image';
import { help as rounddate } from './dict/rounddate';
import { help as rowCount } from './dict/row_count';
import { help as savedLens } from './dict/saved_lens';
import { help as savedMap } from './dict/saved_map';
import { help as savedSearch } from './dict/saved_search';
import { help as savedVisualization } from './dict/saved_visualization';
Expand Down Expand Up @@ -216,6 +217,7 @@ export const getFunctionHelp = (): FunctionHelpDict => ({
revealImage,
rounddate,
rowCount,
savedLens,
savedMap,
savedSearch,
savedVisualization,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ const allowedEmbeddables = {
[EmbeddableTypes.map]: (id: string) => {
return `savedMap id="${id}" | render`;
},
[EmbeddableTypes.lens]: (id: string) => {
return `savedLens id="${id}" | render`;
},
// FIX: Only currently allow Map embeddables
/* [EmbeddableTypes.visualization]: (id: string) => {
return `filters | savedVisualization id="${id}" | render`;
Expand Down
Loading

0 comments on commit 3bd3364

Please sign in to comment.