From cc1dd5297772ecbc718a570128ce22c10065119d Mon Sep 17 00:00:00 2001 From: Yaroslav Kuznietsov Date: Mon, 19 Jul 2021 17:10:18 +0300 Subject: [PATCH] [Canvas] Expression reveal image. Async libs and images loading. (#103399) * Added lazy loading of async libs to storybook. * Refactored lazy loading of import for a storybook. * more refactoring stuff. * more refactoring. * small refactor of waitFor. * Added support of async functions. * Types fix. * fixed docs. * Fixed some mistakes. * Fixed type of tests. * added type for async function to write dicts easier. * Updated stories and view with async image. * Changed all static to async imports. * Removed static import of `elasticLogo`. Fixed type error. * Changed way of returning async functions in `functionWrapper`. * fixed renderer test. * fixed errors. * added outline and fixed types. * added outline everywhere. * waitFor fixed. * removed useless exports. * Fixed type error. * fixed types of dropdown_control.test.ts * fixed `csv.test.ts` types. * Tests fixed. * Fixed storybooks. * Fixed failed tests. * [Canvas] Expression reveal image. (#101987) * expression_reveal_image skeleton. * expression_functions added. * expression_renderers added. * Backup of daily work. * Fixed errors. * Added legacy support. Added button for legacy. * Added storybook. * Removed revealImage from canvas. * setState while rendering error fixed. * tsconfig.json added. * jest.config.js added. * Demo doc added. * Types fixed. * added limits. * Removed not used imports. * i18n namespaces fixed. * Fixed test suite error. * Some errors fixed. * Fixed eslint error. * Removed more unused translations. * Moved UI and elements, related to expressionRevealImage from canvas. * Fixed unused translations errors. * Moved type of element to types. * Fixed types and added service for representing elements, ui and supported renderers to canvas. * Added expression registration to canvas. * Fixed * Fixed mutiple call of the function. * Removed support of a legacy lib for revealImage chart. * Removed legacy presentation_utils plugin import. * Doc error fixed. * Removed useless translations and tried to fix error. * One more fix. * Small imports fix. * Fixed translations. * Made fixes based on nits. * Removed useless params. * fix. * Fixed errors, related to jest and __mocks__. * Removed useless type definition. * Replaced RendererHandlers with IInterpreterRendererHandlers. * fixed supported_shareable. * Moved elements back to canvas. * Moved views to canvas, removed expression service and imported renderer to canvas. * Fixed translations. * Types fix. * Moved libs to presentation utils. * Fixed one mistake. * removed dataurl lib. * Fixed jest files. * elasticLogo removed. * Removed elastic_outline. * removed httpurl. * Removed missing_asset. * removed url. * replaced mostly all tests. * Fixed types. * Fixed types and removed function_wrapper.ts * Fixed types of test helpers. * Changed limits of presentationUtil plugin. * Fixed imports. * One more fix. * Fixed huge size of bundle. * Reduced allow limit for presentationUtil * Updated limits for presentationUtil. * Fixed public API. * fixed type errors. * Moved css to component. * Fixed spaces at element. * Changed order of requiredPlugins. * Updated limits. * Removed unused plugin. * Added rule for allowing import from __stories__ directory. * removed useless comment. * Changed readme.md * Fixed docs error. * A possible of smoke test. * onResize changed to useResizeObserver. * Remove useless events and `useEffect` block. * Changed from passing handlers to separate functions. * `function` moved to `server`. * Fixed eslint error. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> * Fixed mistake of merge. * Storybook fixed. * Fixed a mistake that occurred while resolving merge conflicts. * removed registerFunctionAsync and changed functionWrapper from async to sync. + RepeatImageFunction. * Fixed async functionWrapper usage and fixed `image.test.js` to run. * Added default value for image. * More fixes of async. * Fixed a lot of legacy. * Type fixes. * Fix of fallen tests. * First part of suggestions completed. * Made image required. * Removed useless `async` * Jest test fixed. * Fixed code, based on nits. * Moved to `emotion`. * Fixed prettier error. * replaced jsx pragma with react. * Removed unused jsx. Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> --- .../common/constants.ts | 3 + .../expression_functions/reveal_image.test.ts | 222 ++++++++++-------- .../reveal_image_function.ts | 83 ++++++- .../common/i18n/constants.ts | 10 - .../expression_functions/dict/reveal_image.ts | 61 ----- .../expression_functions/function_errors.ts | 13 - .../expression_functions/function_help.ts | 21 -- .../common/i18n/expression_functions/index.ts | 10 - .../i18n/expression_renderers/dict/index.ts | 9 - .../expression_renderers/dict/reveal_image.ts | 19 -- .../common/i18n/expression_renderers/index.ts | 9 - .../expression_renderers/renderer_strings.ts | 21 -- .../common/i18n/index.ts | 10 - .../common/types/expression_functions.ts | 2 +- .../common/types/expression_renderers.ts | 2 +- .../public/components/reveal_image.scss | 18 -- .../components/reveal_image_component.tsx | 56 +++-- .../reveal_image_renderer.stories.tsx | 24 +- .../reveal_image_renderer.tsx | 21 +- .../lib/test_helpers/function_wrapper.ts | 11 +- .../common/lib/utils/index.ts | 11 +- .../public/__stories__/index.tsx | 1 + .../public/__stories__/render.tsx | 12 +- .../public/__stories__/wait_for.tsx | 41 ++++ .../common/__fixtures__/test_styles.js | 25 +- .../functions/common/alterColumn.test.js | 1 + .../functions/common/case.test.js | 2 +- .../functions/common/container_style.test.js | 13 +- .../functions/common/csv.test.ts | 1 + .../functions/common/dropdown_control.test.ts | 6 - .../functions/common/filterrows.test.js | 2 +- .../functions/common/if.test.js | 1 + .../functions/common/image.test.js | 68 +++--- .../functions/common/image.ts | 16 +- .../functions/common/progress.test.js | 1 + .../functions/common/render.test.js | 9 +- .../functions/common/repeat_image.test.js | 47 ++-- .../functions/common/repeat_image.ts | 14 +- .../functions/common/rounddate.test.js | 1 + .../functions/common/switch.test.js | 1 + .../functions/common/tail.test.js | 1 + .../functions/common/timefilter.test.js | 2 +- .../repeat_image.stories.storyshot | 13 + .../renderers/__stories__/image.stories.tsx | 13 +- .../__stories__/repeat_image.stories.tsx | 25 +- .../canvas_plugin_src/renderers/image.tsx | 8 +- .../renderers/repeat_image.ts | 10 +- .../uis/arguments/image_upload/index.js | 25 +- .../canvas_plugin_src/uis/views/image.js | 57 ++--- x-pack/plugins/canvas/i18n/constants.ts | 3 + .../canvas/i18n/functions/dict/image.ts | 22 +- .../custom_element_modal.stories.tsx | 23 +- .../__stories__/element_card.stories.tsx | 21 +- .../function_reference_generator.tsx | 3 +- .../render_with_fn/render_with_fn.tsx | 2 +- .../__stories__/element_grid.stories.tsx | 45 ++-- .../__stories__/fixtures/test_elements.tsx | 60 ++--- .../saved_elements_modal.stories.tsx | 59 +++-- .../canvas/public/functions/pie.test.js | 6 +- .../canvas/public/functions/plot.test.js | 8 +- .../canvas/public/lib/monaco_language_def.ts | 1 - x-pack/plugins/canvas/public/plugin_api.ts | 4 +- .../public/services/legacy/expressions.ts | 1 + .../services/legacy/stubs/expressions.ts | 10 +- .../canvas/storybook/storyshots.test.tsx | 1 - .../tasks/mocks/customElementService.js | 57 ++--- x-pack/plugins/canvas/types/functions.ts | 7 +- 67 files changed, 758 insertions(+), 627 deletions(-) delete mode 100644 src/plugins/expression_reveal_image/common/i18n/constants.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_functions/dict/reveal_image.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_functions/function_errors.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_functions/function_help.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_functions/index.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/index.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/reveal_image.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_renderers/index.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/expression_renderers/renderer_strings.ts delete mode 100644 src/plugins/expression_reveal_image/common/i18n/index.ts delete mode 100644 src/plugins/expression_reveal_image/public/components/reveal_image.scss create mode 100644 src/plugins/presentation_util/public/__stories__/wait_for.tsx diff --git a/src/plugins/expression_reveal_image/common/constants.ts b/src/plugins/expression_reveal_image/common/constants.ts index 68ac53171ee7f1..2f5a38006832af 100644 --- a/src/plugins/expression_reveal_image/common/constants.ts +++ b/src/plugins/expression_reveal_image/common/constants.ts @@ -7,3 +7,6 @@ */ export const PLUGIN_ID = 'expressionRevealImage'; export const PLUGIN_NAME = 'expressionRevealImage'; + +export const BASE64 = '`base64`'; +export const URL = 'URL'; diff --git a/src/plugins/expression_reveal_image/common/expression_functions/reveal_image.test.ts b/src/plugins/expression_reveal_image/common/expression_functions/reveal_image.test.ts index 633a132fea5e37..999fd31980c6ef 100644 --- a/src/plugins/expression_reveal_image/common/expression_functions/reveal_image.test.ts +++ b/src/plugins/expression_reveal_image/common/expression_functions/reveal_image.test.ts @@ -8,21 +8,26 @@ import { functionWrapper, - elasticOutline, - elasticLogo, + getElasticOutline, + getElasticLogo, } from '../../../presentation_util/common/lib'; -import { getFunctionErrors } from '../i18n'; -import { revealImageFunction } from './reveal_image_function'; +import { revealImageFunction, errors } from './reveal_image_function'; import { Origin } from '../types'; import { ExecutionContext } from 'src/plugins/expressions'; -const errors = getFunctionErrors().revealImage; - describe('revealImageFunction', () => { const fn = functionWrapper(revealImageFunction); - it('returns a render as revealImage', () => { - const result = fn( + let elasticLogo = ''; + let elasticOutline = ''; + + beforeEach(async () => { + elasticLogo = (await getElasticLogo()).elasticLogo; + elasticOutline = (await getElasticOutline()).elasticOutline; + }); + + it('returns a render as revealImage', async () => { + const result = await fn( 0.5, { image: null, @@ -36,130 +41,147 @@ describe('revealImageFunction', () => { }); describe('context', () => { - it('throws when context is not a number between 0 and 1', () => { - expect(() => { - fn( - 10, - { - image: elasticLogo, - emptyImage: elasticOutline, - origin: Origin.TOP, - }, - {} as ExecutionContext - ); - }).toThrow(new RegExp(errors.invalidPercent(10).message)); + it('throws when context is not a number between 0 and 1', async () => { + expect.assertions(2); + await fn( + 10, + { + image: elasticLogo, + emptyImage: elasticOutline, + origin: Origin.TOP, + }, + {} as ExecutionContext + ).catch((e: any) => { + expect(e.message).toMatch(new RegExp(errors.invalidPercent(10).message)); + }); - expect(() => { - fn( - -0.1, - { - image: elasticLogo, - emptyImage: elasticOutline, - origin: Origin.TOP, - }, - {} as ExecutionContext - ); - }).toThrow(new RegExp(errors.invalidPercent(-0.1).message)); + await fn( + -0.1, + { + image: elasticLogo, + emptyImage: elasticOutline, + origin: Origin.TOP, + }, + {} as ExecutionContext + ).catch((e: any) => { + expect(e.message).toMatch(new RegExp(errors.invalidPercent(-0.1).message)); + }); }); }); describe('args', () => { describe('image', () => { - it('sets the image', () => { - const result = fn( - 0.89, - { - emptyImage: null, - origin: Origin.TOP, - image: elasticLogo, - }, - {} as ExecutionContext + it('sets the image', async () => { + const result = ( + await fn( + 0.89, + { + emptyImage: null, + origin: Origin.TOP, + image: elasticLogo, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('image', elasticLogo); }); - it('defaults to the Elastic outline logo', () => { - const result = fn( - 0.89, - { - emptyImage: null, - origin: Origin.TOP, - image: null, - }, - {} as ExecutionContext + it('defaults to the Elastic outline logo', async () => { + const result = ( + await fn( + 0.89, + { + emptyImage: null, + origin: Origin.TOP, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('image', elasticOutline); }); }); describe('emptyImage', () => { - it('sets the background image', () => { - const result = fn( - 0, - { - emptyImage: elasticLogo, - origin: Origin.TOP, - image: null, - }, - {} as ExecutionContext + it('sets the background image', async () => { + const result = ( + await fn( + 0, + { + emptyImage: elasticLogo, + origin: Origin.TOP, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('emptyImage', elasticLogo); }); - it('sets emptyImage to null', () => { - const result = fn( - 0, - { - emptyImage: null, - origin: Origin.TOP, - image: null, - }, - {} as ExecutionContext + it('sets emptyImage to null', async () => { + const result = ( + await fn( + 0, + { + emptyImage: null, + origin: Origin.TOP, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('emptyImage', null); }); }); describe('origin', () => { - it('sets which side to start the reveal from', () => { - let result = fn( - 1, - { - emptyImage: null, - origin: Origin.TOP, - image: null, - }, - {} as ExecutionContext + it('sets which side to start the reveal from', async () => { + let result = ( + await fn( + 1, + { + emptyImage: null, + origin: Origin.TOP, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('origin', 'top'); - result = fn( - 1, - { - emptyImage: null, - origin: Origin.LEFT, - image: null, - }, - {} as ExecutionContext + result = ( + await fn( + 1, + { + emptyImage: null, + origin: Origin.LEFT, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('origin', 'left'); - result = fn( - 1, - { - emptyImage: null, - origin: Origin.BOTTOM, - image: null, - }, - {} as ExecutionContext + result = ( + await fn( + 1, + { + emptyImage: null, + origin: Origin.BOTTOM, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('origin', 'bottom'); - result = fn( - 1, - { - emptyImage: null, - origin: Origin.RIGHT, - image: null, - }, - {} as ExecutionContext + result = ( + await fn( + 1, + { + emptyImage: null, + origin: Origin.RIGHT, + image: null, + }, + {} as ExecutionContext + ) ).value; expect(result).toHaveProperty('origin', 'right'); }); diff --git a/src/plugins/expression_reveal_image/common/expression_functions/reveal_image_function.ts b/src/plugins/expression_reveal_image/common/expression_functions/reveal_image_function.ts index 33e61e85f95315..7056bb10518e89 100644 --- a/src/plugins/expression_reveal_image/common/expression_functions/reveal_image_function.ts +++ b/src/plugins/expression_reveal_image/common/expression_functions/reveal_image_function.ts @@ -6,13 +6,77 @@ * Side Public License, v 1. */ -import { resolveWithMissingImage, elasticOutline } from '../../../presentation_util/common/lib'; -import { getFunctionHelp, getFunctionErrors } from '../i18n'; -import { ExpressionRevealImageFunction, Origin } from '../types'; +import { i18n } from '@kbn/i18n'; +import { + resolveWithMissingImage, + getElasticOutline, + isValidUrl, +} from '../../../presentation_util/common/lib'; +import { ExpressionRevealImageFunction, Origin, Position } from '../../common/types'; +import { BASE64, URL } from '../../common/constants'; + +const strings = { + help: i18n.translate('expressionRevealImage.functions.revealImageHelpText', { + defaultMessage: 'Configures an image reveal element.', + }), + args: { + image: i18n.translate('expressionRevealImage.functions.revealImage.args.imageHelpText', { + defaultMessage: + 'The image to reveal. Provide an image asset as a {BASE64} data {URL}, ' + + 'or pass in a sub-expression.', + values: { + BASE64, + URL, + }, + }), + emptyImage: i18n.translate( + 'expressionRevealImage.functions.revealImage.args.emptyImageHelpText', + { + defaultMessage: + 'An optional background image to reveal over. ' + + 'Provide an image asset as a `{BASE64}` data {URL}, or pass in a sub-expression.', + values: { + BASE64, + URL, + }, + } + ), + origin: i18n.translate('expressionRevealImage.functions.revealImage.args.originHelpText', { + defaultMessage: 'The position to start the image fill. For example, {list}, or {end}.', + values: { + list: Object.values(Position) + .slice(0, -1) + .map((position) => `\`"${position}"\``) + .join(', '), + end: Object.values(Position).slice(-1)[0], + }, + }), + }, +}; + +export const errors = { + invalidPercent: (percent: number) => + new Error( + i18n.translate('expressionRevealImage.functions.revealImage.invalidPercentErrorMessage', { + defaultMessage: "Invalid value: '{percent}'. Percentage must be between 0 and 1", + values: { + percent, + }, + }) + ), + invalidImageUrl: (imageUrl: string) => + new Error( + i18n.translate('expressionRevealImage.functions.revealImage.invalidImageUrl', { + defaultMessage: "Invalid image url: '{imageUrl}'.", + values: { + imageUrl, + }, + }) + ), +}; export const revealImageFunction: ExpressionRevealImageFunction = () => { - const { help, args: argHelp } = getFunctionHelp().revealImage; - const errors = getFunctionErrors().revealImage; + const { help, args: argHelp } = strings; return { name: 'revealImage', @@ -24,7 +88,7 @@ export const revealImageFunction: ExpressionRevealImageFunction = () => { image: { types: ['string', 'null'], help: argHelp.image, - default: elasticOutline, + default: null, }, emptyImage: { types: ['string', 'null'], @@ -38,11 +102,16 @@ export const revealImageFunction: ExpressionRevealImageFunction = () => { options: Object.values(Origin), }, }, - fn: (percent, args) => { + fn: async (percent, args) => { if (percent > 1 || percent < 0) { throw errors.invalidPercent(percent); } + if (args.image && !isValidUrl(args.image)) { + throw errors.invalidImageUrl(args.image); + } + + const { elasticOutline } = await getElasticOutline(); return { type: 'render', as: 'revealImage', diff --git a/src/plugins/expression_reveal_image/common/i18n/constants.ts b/src/plugins/expression_reveal_image/common/i18n/constants.ts deleted file mode 100644 index 413f376515a335..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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 const BASE64 = '`base64`'; -export const URL = 'URL'; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_functions/dict/reveal_image.ts b/src/plugins/expression_reveal_image/common/i18n/expression_functions/dict/reveal_image.ts deleted file mode 100644 index ccf9967bd6a65c..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_functions/dict/reveal_image.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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'; -import { Position } from '../../../types'; -import { BASE64, URL } from '../../constants'; - -export const help = { - help: i18n.translate('expressionRevealImage.functions.revealImageHelpText', { - defaultMessage: 'Configures an image reveal element.', - }), - args: { - image: i18n.translate('expressionRevealImage.functions.revealImage.args.imageHelpText', { - defaultMessage: - 'The image to reveal. Provide an image asset as a {BASE64} data {URL}, ' + - 'or pass in a sub-expression.', - values: { - BASE64, - URL, - }, - }), - emptyImage: i18n.translate( - 'expressionRevealImage.functions.revealImage.args.emptyImageHelpText', - { - defaultMessage: - 'An optional background image to reveal over. ' + - 'Provide an image asset as a `{BASE64}` data {URL}, or pass in a sub-expression.', - values: { - BASE64, - URL, - }, - } - ), - origin: i18n.translate('expressionRevealImage.functions.revealImage.args.originHelpText', { - defaultMessage: 'The position to start the image fill. For example, {list}, or {end}.', - values: { - list: Object.values(Position) - .slice(0, -1) - .map((position) => `\`"${position}"\``) - .join(', '), - end: Object.values(Position).slice(-1)[0], - }, - }), - }, -}; -export const errors = { - invalidPercent: (percent: number) => - new Error( - i18n.translate('expressionRevealImage.functions.revealImage.invalidPercentErrorMessage', { - defaultMessage: "Invalid value: '{percent}'. Percentage must be between 0 and 1", - values: { - percent, - }, - }) - ), -}; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_errors.ts b/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_errors.ts deleted file mode 100644 index 09cd26c9e620b9..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_errors.ts +++ /dev/null @@ -1,13 +0,0 @@ -/* - * 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 { errors as revealImage } from './dict/reveal_image'; - -export const getFunctionErrors = () => ({ - revealImage, -}); diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_help.ts b/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_help.ts deleted file mode 100644 index 30e79b120771b7..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_functions/function_help.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 { help as revealImage } from './dict/reveal_image'; - -/** - * Help text for Canvas Functions should be properly localized. This function will - * return a dictionary of help strings, organized by `ExpressionFunctionDefinition` - * specification and then by available arguments within each `ExpressionFunctionDefinition`. - * - * This a function, rather than an object, to future-proof string initialization, - * if ever necessary. - */ -export const getFunctionHelp = () => ({ - revealImage, -}); diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_functions/index.ts b/src/plugins/expression_reveal_image/common/i18n/expression_functions/index.ts deleted file mode 100644 index 3d36b123421f48..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_functions/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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 './function_help'; -export * from './function_errors'; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/index.ts b/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/index.ts deleted file mode 100644 index 4f70f9d30b74bb..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 { strings as revealImage } from './reveal_image'; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/reveal_image.ts b/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/reveal_image.ts deleted file mode 100644 index a32fdbd4c0b50f..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/dict/reveal_image.ts +++ /dev/null @@ -1,19 +0,0 @@ -/* - * 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 strings = { - getDisplayName: () => - i18n.translate('expressionRevealImage.renderer.revealImage.displayName', { - defaultMessage: 'Image reveal', - }), - getHelpDescription: () => - i18n.translate('expressionRevealImage.renderer.revealImage.helpDescription', { - defaultMessage: 'Reveal a percentage of an image to make a custom gauge-style chart', - }), -}; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/index.ts b/src/plugins/expression_reveal_image/common/i18n/expression_renderers/index.ts deleted file mode 100644 index 7e637f240d15c9..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -/* - * 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 './renderer_strings'; diff --git a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/renderer_strings.ts b/src/plugins/expression_reveal_image/common/i18n/expression_renderers/renderer_strings.ts deleted file mode 100644 index b74230a2a5d76e..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/expression_renderers/renderer_strings.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* - * 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 { revealImage } from './dict'; - -/** - * Help text for Canvas Functions should be properly localized. This function will - * return a dictionary of help strings, organized by `ExpressionFunctionDefinition` - * specification and then by available arguments within each `ExpressionFunctionDefinition`. - * - * This a function, rather than an object, to future-proof string initialization, - * if ever necessary. - */ -export const getRendererStrings = () => ({ - revealImage, -}); diff --git a/src/plugins/expression_reveal_image/common/i18n/index.ts b/src/plugins/expression_reveal_image/common/i18n/index.ts deleted file mode 100644 index 9c50bfab1305d3..00000000000000 --- a/src/plugins/expression_reveal_image/common/i18n/index.ts +++ /dev/null @@ -1,10 +0,0 @@ -/* - * 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 './expression_functions'; -export * from './expression_renderers'; diff --git a/src/plugins/expression_reveal_image/common/types/expression_functions.ts b/src/plugins/expression_reveal_image/common/types/expression_functions.ts index ee291e204acfb8..2d836bf8ad997f 100644 --- a/src/plugins/expression_reveal_image/common/types/expression_functions.ts +++ b/src/plugins/expression_reveal_image/common/types/expression_functions.ts @@ -31,7 +31,7 @@ export type ExpressionRevealImageFunction = () => ExpressionFunctionDefinition< 'revealImage', number, Arguments, - ExpressionValueRender + Promise> >; export enum Position { diff --git a/src/plugins/expression_reveal_image/common/types/expression_renderers.ts b/src/plugins/expression_reveal_image/common/types/expression_renderers.ts index 77dacaefc1bd1f..b04c292433f9b6 100644 --- a/src/plugins/expression_reveal_image/common/types/expression_renderers.ts +++ b/src/plugins/expression_reveal_image/common/types/expression_renderers.ts @@ -11,7 +11,7 @@ export type OriginString = 'bottom' | 'left' | 'top' | 'right'; export interface RevealImageRendererConfig { percent: number; origin?: OriginString; - image?: string; + image: string; emptyImage?: string; } diff --git a/src/plugins/expression_reveal_image/public/components/reveal_image.scss b/src/plugins/expression_reveal_image/public/components/reveal_image.scss deleted file mode 100644 index f94668b7cdfa2f..00000000000000 --- a/src/plugins/expression_reveal_image/public/components/reveal_image.scss +++ /dev/null @@ -1,18 +0,0 @@ -.revealImage { - height: 100%; - width: 100%; - display: flex; - align-items: center; - justify-content: center; - pointer-events: none; - - .revealImageAligner { - background-size: contain; - background-repeat: no-repeat; - } - - // disables selection and dragging - .revealImage__image { - user-select: none; - } -} diff --git a/src/plugins/expression_reveal_image/public/components/reveal_image_component.tsx b/src/plugins/expression_reveal_image/public/components/reveal_image_component.tsx index a9c24fca78d9b6..d20bbdc1bf1916 100644 --- a/src/plugins/expression_reveal_image/public/components/reveal_image_component.tsx +++ b/src/plugins/expression_reveal_image/public/components/reveal_image_component.tsx @@ -9,9 +9,27 @@ import React, { useRef, useState, useEffect, useCallback } from 'react'; import { useResizeObserver } from '@elastic/eui'; import { IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { css, CSSObject } from '@emotion/react'; import { NodeDimensions, RevealImageRendererConfig, OriginString } from '../../common/types'; -import { isValidUrl, elasticOutline } from '../../../presentation_util/public'; -import './reveal_image.scss'; +import { isValidUrl } from '../../../presentation_util/public'; + +const revealImageParentStyle = css` + height: 100%; + width: 100%; + display: flex; + align-items: center; + justify-content: center; + pointer-events: none; +`; + +const revealImageAlignerStyle: CSSObject = { + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', +}; + +const revealImageStyle: CSSObject = { + userSelect: 'none', +}; interface RevealImageComponentProps extends RevealImageRendererConfig { onLoaded: IInterpreterRenderHandlers['done']; @@ -19,8 +37,8 @@ interface RevealImageComponentProps extends RevealImageRendererConfig { } interface ImageStyles { - width?: string; - height?: string; + width?: number | string; + height?: number | string; clipPath?: string; } @@ -48,6 +66,7 @@ function RevealImageComponent({ // modify the top-level container class parentNode.className = 'revealImage'; + parentNode.setAttribute('style', revealImageParentStyle.styles); // set up the overlay image const updateImageView = useCallback(() => { @@ -89,43 +108,46 @@ function RevealImageComponent({ }; if (imgDimensions.ratio > domNodeDimensions.ratio) { - imgStyles.height = `${domNodeDimensions.height}px`; + imgStyles.height = domNodeDimensions.height; imgStyles.width = 'initial'; } else { - imgStyles.width = `${domNodeDimensions.width}px`; + imgStyles.width = domNodeDimensions.width; imgStyles.height = 'initial'; } return imgStyles; } - const imgSrc = isValidUrl(image ?? '') ? image : elasticOutline; - - const alignerStyles: AlignerStyles = {}; + const additionaAlignerStyles: AlignerStyles = {}; if (isValidUrl(emptyImage ?? '')) { // only use empty image if one is provided - alignerStyles.backgroundImage = `url(${emptyImage})`; + additionaAlignerStyles.backgroundImage = `url(${emptyImage})`; } - let imgStyles: ImageStyles = {}; - if (imgRef.current && loaded) imgStyles = getImageSizeStyle(); + let additionalImgStyles: ImageStyles = {}; + if (imgRef.current && loaded) additionalImgStyles = getImageSizeStyle(); - imgStyles.clipPath = getClipPath(percent, origin); + additionalImgStyles.clipPath = getClipPath(percent, origin); if (imgRef.current && loaded) { imgRef.current.style.setProperty('-webkit-clip-path', getClipPath(percent, origin)); } return ( -
+
); diff --git a/src/plugins/expression_reveal_image/public/expression_renderers/__stories__/reveal_image_renderer.stories.tsx b/src/plugins/expression_reveal_image/public/expression_renderers/__stories__/reveal_image_renderer.stories.tsx index bc70b3685e24e1..863d8d1000f385 100644 --- a/src/plugins/expression_reveal_image/public/expression_renderers/__stories__/reveal_image_renderer.stories.tsx +++ b/src/plugins/expression_reveal_image/public/expression_renderers/__stories__/reveal_image_renderer.stories.tsx @@ -9,18 +9,30 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { revealImageRenderer } from '../'; -import { elasticOutline, elasticLogo } from '../../../../presentation_util/public'; -import { Render } from '../../../../presentation_util/public/__stories__'; - +import { getElasticOutline, getElasticLogo } from '../../../../presentation_util/public'; +import { Render, waitFor } from '../../../../presentation_util/public/__stories__'; import { Origin } from '../../../common/types/expression_functions'; -storiesOf('renderers/revealImage', module).add('default', () => { +const Renderer = ({ + elasticLogo, + elasticOutline, +}: { + elasticLogo: string; + elasticOutline: string; +}) => { const config = { image: elasticLogo, emptyImage: elasticOutline, origin: Origin.LEFT, percent: 0.45, }; - return ; -}); +}; + +storiesOf('renderers/revealImage', module).add( + 'default', + (_, props) => ( + + ), + { decorators: [waitFor(getElasticLogo()), waitFor(getElasticOutline())] } +); diff --git a/src/plugins/expression_reveal_image/public/expression_renderers/reveal_image_renderer.tsx b/src/plugins/expression_reveal_image/public/expression_renderers/reveal_image_renderer.tsx index 4d84de3da994ca..c89272ba58add6 100644 --- a/src/plugins/expression_reveal_image/public/expression_renderers/reveal_image_renderer.tsx +++ b/src/plugins/expression_reveal_image/public/expression_renderers/reveal_image_renderer.tsx @@ -9,21 +9,30 @@ import React, { lazy } from 'react'; import { render, unmountComponentAtNode } from 'react-dom'; import { I18nProvider } from '@kbn/i18n/react'; import { ExpressionRenderDefinition, IInterpreterRenderHandlers } from 'src/plugins/expressions'; +import { i18n } from '@kbn/i18n'; import { withSuspense } from '../../../presentation_util/public'; -import { getRendererStrings } from '../../common/i18n'; import { RevealImageRendererConfig } from '../../common/types'; -const { revealImage: revealImageStrings } = getRendererStrings(); +export const strings = { + getDisplayName: () => + i18n.translate('expressionRevealImage.renderer.revealImage.displayName', { + defaultMessage: 'Image reveal', + }), + getHelpDescription: () => + i18n.translate('expressionRevealImage.renderer.revealImage.helpDescription', { + defaultMessage: 'Reveal a percentage of an image to make a custom gauge-style chart', + }), +}; const LazyRevealImageComponent = lazy(() => import('../components/reveal_image_component')); const RevealImageComponent = withSuspense(LazyRevealImageComponent, null); export const revealImageRenderer = (): ExpressionRenderDefinition => ({ name: 'revealImage', - displayName: revealImageStrings.getDisplayName(), - help: revealImageStrings.getHelpDescription(), + displayName: strings.getDisplayName(), + help: strings.getHelpDescription(), reuseDomNode: true, - render: async ( + render: ( domNode: HTMLElement, config: RevealImageRendererConfig, handlers: IInterpreterRenderHandlers @@ -34,7 +43,7 @@ export const revealImageRenderer = (): ExpressionRenderDefinition - + , domNode ); diff --git a/src/plugins/presentation_util/common/lib/test_helpers/function_wrapper.ts b/src/plugins/presentation_util/common/lib/test_helpers/function_wrapper.ts index 4ec02fd622cf74..51e82d785e86c2 100644 --- a/src/plugins/presentation_util/common/lib/test_helpers/function_wrapper.ts +++ b/src/plugins/presentation_util/common/lib/test_helpers/function_wrapper.ts @@ -13,8 +13,15 @@ import { ExpressionFunctionDefinition, } from '../../../../expressions/common'; -type FnType = () => typeof typeSpecs[number] & - ExpressionFunctionDefinition, ExpressionValueBoxed>; +type DefaultFnResultType = typeof typeSpecs[number] & + ExpressionFunctionDefinition< + string, + any, + Record, + ExpressionValueBoxed | Promise> + >; + +type FnType = () => DefaultFnResultType; // It takes a function spec and passes in default args into the spec fn export const functionWrapper = (fnSpec: FnType): ReturnType['fn'] => { diff --git a/src/plugins/presentation_util/common/lib/utils/index.ts b/src/plugins/presentation_util/common/lib/utils/index.ts index eed4acf78b2bef..232ec09cf8b06d 100644 --- a/src/plugins/presentation_util/common/lib/utils/index.ts +++ b/src/plugins/presentation_util/common/lib/utils/index.ts @@ -7,9 +7,14 @@ */ export * from './dataurl'; -export * from './elastic_logo'; -export * from './elastic_outline'; export * from './httpurl'; -export * from './missing_asset'; export * from './resolve_dataurl'; export * from './url'; + +export async function getElasticLogo() { + return await import('./elastic_logo'); +} + +export async function getElasticOutline() { + return await import('./elastic_outline'); +} diff --git a/src/plugins/presentation_util/public/__stories__/index.tsx b/src/plugins/presentation_util/public/__stories__/index.tsx index 078a16cb8cab24..a5633c4a2dd1fb 100644 --- a/src/plugins/presentation_util/public/__stories__/index.tsx +++ b/src/plugins/presentation_util/public/__stories__/index.tsx @@ -7,3 +7,4 @@ */ export * from './render'; +export * from './wait_for'; diff --git a/src/plugins/presentation_util/public/__stories__/render.tsx b/src/plugins/presentation_util/public/__stories__/render.tsx index 29d95e6bf28191..2588d2e3294ae6 100644 --- a/src/plugins/presentation_util/public/__stories__/render.tsx +++ b/src/plugins/presentation_util/public/__stories__/render.tsx @@ -31,13 +31,11 @@ interface RenderAdditionalProps { handlers?: IInterpreterRenderHandlers; } -export const Render = ({ - renderer, - config, - ...rest -}: Renderer extends () => ExpressionRenderDefinition - ? { renderer: Renderer; config: Config } & RenderAdditionalProps - : { renderer: undefined; config: undefined } & RenderAdditionalProps) => { +export type RenderProps = T extends () => ExpressionRenderDefinition + ? { renderer: T; config: Config } & RenderAdditionalProps + : { renderer: undefined; config: undefined } & RenderAdditionalProps; + +export const Render = ({ renderer, config, ...rest }: RenderProps) => { const { height, width, handlers } = { height: '200px', width: '200px', diff --git a/src/plugins/presentation_util/public/__stories__/wait_for.tsx b/src/plugins/presentation_util/public/__stories__/wait_for.tsx new file mode 100644 index 00000000000000..b6421ec7adf5e3 --- /dev/null +++ b/src/plugins/presentation_util/public/__stories__/wait_for.tsx @@ -0,0 +1,41 @@ +/* + * 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 React, { useState, useEffect, useRef, ReactElement } from 'react'; +import { act } from 'react-test-renderer'; +import { Story } from '@storybook/react'; +import { StoryFnReactReturnType } from '@storybook/react/dist/client/preview/types'; +import { EuiLoadingSpinner } from '@elastic/eui'; + +export const waitFor = ( + waitTarget: Promise, + spinner: ReactElement | null = +) => (CurrentStory: Story) => { + const [storyComponent, setStory] = useState(); + const componentIsMounted = useRef(false); + + useEffect(() => { + componentIsMounted.current = true; + return () => { + componentIsMounted.current = false; + }; + }, []); + + useEffect(() => { + if (!storyComponent) { + waitTarget.then((waitedTarget: any) => { + if (!componentIsMounted.current) return; + act(() => { + setStory(); + }); + }); + } + }, [CurrentStory, storyComponent]); + + return storyComponent ?? spinner; +}; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js index fa831cacbcb18e..4f621bdd94b35b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/__fixtures__/test_styles.js @@ -5,7 +5,7 @@ * 2.0. */ -import { elasticLogo } from '../../../../../../../src/plugins/presentation_util/common/lib'; +import { getElasticLogo } from '../../../../../../../src/plugins/presentation_util/common/lib'; export const fontStyle = { type: 'style', @@ -23,16 +23,19 @@ export const fontStyle = { 'font-family:Chalkboard, serif;font-weight:bolder;font-style:normal;text-decoration:underline;color:pink;text-align:center;font-size:14px;line-height:21px', }; -export const containerStyle = { - type: 'containerStyle', - border: '3px dotted blue', - borderRadius: '5px', - padding: '10px', - backgroundColor: 'red', - backgroundImage: `url(${elasticLogo})`, - opacity: 0.5, - backgroundSize: 'contain', - backgroundRepeat: 'no-repeat', +export const getContainerStyle = async () => { + const { elasticLogo } = await getElasticLogo(); + return { + type: 'containerStyle', + border: '3px dotted blue', + borderRadius: '5px', + padding: '10px', + backgroundColor: 'red', + backgroundImage: `url(${elasticLogo})`, + opacity: 0.5, + backgroundSize: 'contain', + backgroundRepeat: 'no-repeat', + }; }; export const defaultStyle = { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js index 85e062f454bc5c..d2a7cd5565ece1 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/alterColumn.test.js @@ -14,6 +14,7 @@ const errors = getFunctionErrors().alterColumn; describe('alterColumn', () => { const fn = functionWrapper(alterColumn); + const nameColumnIndex = testTable.columns.findIndex(({ name }) => name === 'name'); const timeColumnIndex = testTable.columns.findIndex(({ name }) => name === 'time'); const priceColumnIndex = testTable.columns.findIndex(({ name }) => name === 'price'); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js index d5621943bccafc..5bdc013eff594c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/case.test.js @@ -11,8 +11,8 @@ import { functionWrapper } from '../../../../../../src/plugins/presentation_util import { caseFn } from './case'; describe('case', () => { - const fn = functionWrapper(caseFn); let testScheduler; + const fn = functionWrapper(caseFn); beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected)); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js index 7a3599f47ec861..15c7ccdbf5ce07 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/container_style.test.js @@ -6,8 +6,8 @@ */ import { - elasticLogo, functionWrapper, + getElasticLogo, } from '../../../../../../src/plugins/presentation_util/common/lib'; import { getFunctionErrors } from '../../../i18n'; import { containerStyle } from './containerStyle'; @@ -17,14 +17,21 @@ const errors = getFunctionErrors().containerStyle; describe('containerStyle', () => { const fn = functionWrapper(containerStyle); - describe('default output', () => { - const result = fn(null); + let elasticLogo; + beforeEach(async () => { + elasticLogo = (await getElasticLogo()).elasticLogo; + }); + describe('default output', () => { it('returns a containerStyle', () => { + const result = fn(null); + expect(result).toHaveProperty('type', 'containerStyle'); }); it('all style properties except `overflow` are omitted if args not provided', () => { + const result = fn(null); + expect(Object.keys(result)).toHaveLength(2); expect(result).toHaveProperty('type'); expect(result).toHaveProperty('overflow'); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.ts index cfef618bee39d0..6feb22b2ef15e2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/csv.test.ts @@ -15,6 +15,7 @@ const errors = getFunctionErrors().csv; describe('csv', () => { const fn = functionWrapper(csv); + const expected: Datatable = { type: 'datatable', columns: [ diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.ts index 254efd9f5f0d9d..6f785f1b9d4791 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/dropdown_control.test.ts @@ -95,11 +95,5 @@ describe('dropdownControl', () => { ?.value ).toHaveProperty('column', 'price'); }); - - it('sets column to undefined if no args are provided', () => { - expect( - fn(testTable, {}, {} as ExecutionContext)?.value - ).toHaveProperty('column', undefined); - }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js index edc2c1db18f640..f81e3ae2413043 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/filterrows.test.js @@ -15,8 +15,8 @@ const inStock = (datatable) => of(datatable.rows[0].in_stock); const returnFalse = () => of(false); describe('filterrows', () => { - const fn = functionWrapper(filterrows); let testScheduler; + const fn = functionWrapper(filterrows); beforeEach(() => { testScheduler = new TestScheduler((actual, expected) => expect(actual).toStrictEqual(expected)); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js index df576a6a2507f6..fbfcdef076110d 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/if.test.js @@ -12,6 +12,7 @@ import { ifFn } from './if'; describe('if', () => { const fn = functionWrapper(ifFn); + let testScheduler; beforeEach(() => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js index 45b26cd25937da..862560e5643d7e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.test.js @@ -7,61 +7,67 @@ import expect from '@kbn/expect'; import { - elasticLogo, - elasticOutline, + getElasticLogo, + getElasticOutline, + functionWrapper, } from '../../../../../../src/plugins/presentation_util/common/lib'; -// import { image } from './image'; +import { image } from './image'; // TODO: the test was not running and is not up to date -describe.skip('image', () => { - const fn = jest.fn(); +describe('image', () => { + const fn = functionWrapper(image); - it('returns an image object using a dataUrl', () => { - const result = fn(null, { dataurl: elasticOutline, mode: 'cover' }); + let elasticLogo; + let elasticOutline; + beforeEach(async () => { + elasticLogo = (await getElasticLogo()).elasticLogo; + elasticOutline = (await getElasticOutline()).elasticOutline; + }); + + it('returns an image object using a dataUrl', async () => { + const result = await fn(null, { dataurl: elasticOutline, mode: 'cover' }); expect(result).to.have.property('type', 'image'); }); describe('args', () => { describe('dataurl', () => { - it('sets the source of the image using dataurl', () => { - const result = fn(null, { dataurl: elasticOutline }); + it('sets the source of the image using dataurl', async () => { + const result = await fn(null, { dataurl: elasticOutline }); expect(result).to.have.property('dataurl', elasticOutline); }); - it.skip('sets the source of the image using url', () => { + it.skip('sets the source of the image using url', async () => { // This is skipped because functionWrapper doesn't use the actual // interpreter and doesn't resolve aliases - const result = fn(null, { url: elasticOutline }); + const result = await fn(null, { url: elasticOutline }); expect(result).to.have.property('dataurl', elasticOutline); }); - it('defaults to the elasticLogo if not provided', () => { - const result = fn(null); + it('defaults to the elasticLogo if not provided', async () => { + const result = await fn(null); expect(result).to.have.property('dataurl', elasticLogo); }); }); - describe('mode', () => { - it('sets the mode', () => { - it('to contain', () => { - const result = fn(null, { mode: 'contain' }); - expect(result).to.have.property('mode', 'contain'); - }); + describe('sets the mode', () => { + it('to contain', async () => { + const result = await fn(null, { mode: 'contain' }); + expect(result).to.have.property('mode', 'contain'); + }); - it('to cover', () => { - const result = fn(null, { mode: 'cover' }); - expect(result).to.have.property('mode', 'cover'); - }); + it('to cover', async () => { + const result = await fn(null, { mode: 'cover' }); + expect(result).to.have.property('mode', 'cover'); + }); - it('to stretch', () => { - const result = fn(null, { mode: 'stretch' }); - expect(result).to.have.property('mode', 'stretch'); - }); + it('to stretch', async () => { + const result = await fn(null, { mode: 'stretch' }); + expect(result).to.have.property('mode', '100% 100%'); + }); - it("defaults to 'contain' if not provided", () => { - const result = fn(null); - expect(result).to.have.property('mode', 'contain'); - }); + it("defaults to 'contain' if not provided", async () => { + const result = await fn(null); + expect(result).to.have.property('mode', 'contain'); }); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts index c3e64e48b23fc8..e661a15cea3aef 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/image.ts @@ -7,8 +7,9 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { getFunctionHelp, getFunctionErrors } from '../../../i18n'; + import { - elasticLogo, + getElasticLogo, resolveWithMissingImage, } from '../../../../../../src/plugins/presentation_util/common/lib'; @@ -29,10 +30,9 @@ export interface Return { dataurl: string; } -export function image(): ExpressionFunctionDefinition<'image', null, Arguments, Return> { +export function image(): ExpressionFunctionDefinition<'image', null, Arguments, Promise> { const { help, args: argHelp } = getFunctionHelp().image; const errors = getFunctionErrors().image; - return { name: 'image', aliases: [], @@ -45,7 +45,7 @@ export function image(): ExpressionFunctionDefinition<'image', null, Arguments, types: ['string', 'null'], help: argHelp.dataurl, aliases: ['_', 'url'], - default: elasticLogo, + default: null, }, mode: { types: ['string'], @@ -54,13 +54,17 @@ export function image(): ExpressionFunctionDefinition<'image', null, Arguments, options: Object.values(ImageMode), }, }, - fn: (input, { dataurl, mode }) => { + fn: async (input, { dataurl, mode }) => { if (!mode || !Object.values(ImageMode).includes(mode)) { throw errors.invalidImageMode(); } + const { elasticLogo } = await getElasticLogo(); - const modeStyle = mode === 'stretch' ? '100% 100%' : mode; + if (dataurl === null) { + dataurl = elasticLogo; + } + const modeStyle = mode === 'stretch' ? '100% 100%' : mode; return { type: 'image', mode: modeStyle, diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js index 6438e2a4d19c0d..5f44428abf03a8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/progress.test.js @@ -16,6 +16,7 @@ const errors = getFunctionErrors().progress; // TODO: this test was not running and is not up to date describe.skip('progress', () => { const fn = functionWrapper(progress); + const value = 0.33; it('returns a render as progress', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js index 3248af55040939..1725af3522ba3c 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/render.test.js @@ -8,7 +8,7 @@ import { functionWrapper } from '../../../../../../src/plugins/presentation_util/common/lib'; import { DEFAULT_ELEMENT_CSS } from '../../../common/lib/constants'; import { testTable } from './__fixtures__/test_tables'; -import { fontStyle, containerStyle } from './__fixtures__/test_styles'; +import { fontStyle, getContainerStyle } from './__fixtures__/test_styles'; import { render } from './render'; const renderTable = { @@ -25,7 +25,12 @@ const renderTable = { describe('render', () => { const fn = functionWrapper(render); - it('returns a render', () => { + let containerStyle; + beforeEach(async () => { + containerStyle = await getContainerStyle(); + }); + + it('returns a render', async () => { const result = fn(renderTable, { as: 'debug', css: '".canvasRenderEl { background-color: red; }"', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js index 97f0552721ccfb..42569e26e426cf 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.test.js @@ -6,8 +6,8 @@ */ import { - elasticLogo, - elasticOutline, + getElasticLogo, + getElasticOutline, functionWrapper, } from '../../../../../../src/plugins/presentation_util/common/lib'; import { repeatImage } from './repeat_image'; @@ -15,55 +15,62 @@ import { repeatImage } from './repeat_image'; describe('repeatImage', () => { const fn = functionWrapper(repeatImage); - it('returns a render as repeatImage', () => { - const result = fn(10); + let elasticLogo; + let elasticOutline; + beforeEach(async () => { + elasticLogo = await (await getElasticLogo()).elasticLogo; + elasticOutline = await (await getElasticOutline()).elasticOutline; + }); + + it('returns a render as repeatImage', async () => { + const result = await fn(10); expect(result).toHaveProperty('type', 'render'); expect(result).toHaveProperty('as', 'repeatImage'); }); describe('args', () => { describe('image', () => { - it('sets the source of the repeated image', () => { - const result = fn(10, { image: elasticLogo }).value; + it('sets the source of the repeated image', async () => { + const result = (await fn(10, { image: elasticLogo })).value; expect(result).toHaveProperty('image', elasticLogo); }); - it('defaults to the Elastic outline logo', () => { - const result = fn(100000).value; + it('defaults to the Elastic outline logo', async () => { + const result = (await fn(100000)).value; expect(result).toHaveProperty('image', elasticOutline); }); }); describe('size', () => { - it('sets the size of the image', () => { - const result = fn(-5, { size: 200 }).value; + it('sets the size of the image', async () => { + const result = (await fn(-5, { size: 200 })).value; expect(result).toHaveProperty('size', 200); }); - it('defaults to 100', () => { - const result = fn(-5).value; + it('defaults to 100', async () => { + const result = (await fn(-5)).value; expect(result).toHaveProperty('size', 100); }); }); describe('max', () => { - it('sets the maximum number of a times the image is repeated', () => { - const result = fn(100000, { max: 20 }).value; + it('sets the maximum number of a times the image is repeated', async () => { + const result = (await fn(100000, { max: 20 })).value; expect(result).toHaveProperty('max', 20); }); - it('defaults to 1000', () => { - const result = fn(100000).value; + it('defaults to 1000', async () => { + const result = (await fn(100000)).value; expect(result).toHaveProperty('max', 1000); }); }); describe('emptyImage', () => { - it('returns repeatImage object with emptyImage as undefined', () => { - const result = fn(100000, { emptyImage: elasticLogo }).value; + it('returns repeatImage object with emptyImage as undefined', async () => { + const result = (await fn(100000, { emptyImage: elasticLogo })).value; expect(result).toHaveProperty('emptyImage', elasticLogo); }); - it('sets emptyImage to null', () => { - const result = fn(100000).value; + it('sets emptyImage to null', async () => { + const result = (await fn(100000)).value; expect(result).toHaveProperty('emptyImage', null); }); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.ts b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.ts index 904b2478760abb..751573e27183b4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/repeat_image.ts @@ -7,7 +7,7 @@ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; import { - elasticOutline, + getElasticOutline, resolveWithMissingImage, } from '../../../../../../src/plugins/presentation_util/common/lib'; import { Render } from '../../../types'; @@ -32,10 +32,9 @@ export function repeatImage(): ExpressionFunctionDefinition< 'repeatImage', number, Arguments, - Render + Promise> > { const { help, args: argHelp } = getFunctionHelp().repeatImage; - return { name: 'repeatImage', aliases: [], @@ -51,7 +50,7 @@ export function repeatImage(): ExpressionFunctionDefinition< image: { types: ['string', 'null'], help: argHelp.image, - default: elasticOutline, + default: null, }, max: { types: ['number'], @@ -64,7 +63,12 @@ export function repeatImage(): ExpressionFunctionDefinition< help: argHelp.size, }, }, - fn: (count, args) => { + fn: async (count, args) => { + const { elasticOutline } = await getElasticOutline(); + if (args.image === null) { + args.image = elasticOutline; + } + return { type: 'render', as: 'repeatImage', diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js index 0ef832d9732711..987096cc0d3dc4 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/rounddate.test.js @@ -10,6 +10,7 @@ import { rounddate } from './rounddate'; describe('rounddate', () => { const fn = functionWrapper(rounddate); + const date = new Date('2011-10-31T00:00:00.000Z').valueOf(); it('returns date in ms from date in ms or ISO8601 string', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js index c6f592889c9912..ffa1557d2b54ed 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/switch.test.js @@ -12,6 +12,7 @@ import { switchFn } from './switch'; describe('switch', () => { const fn = functionWrapper(switchFn); + const getter = (value) => () => of(value); const mockCases = [ { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js index 420489754d20e0..75744f91ccb579 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/tail.test.js @@ -11,6 +11,7 @@ import { tail } from './tail'; describe('tail', () => { const fn = functionWrapper(tail); + const lastIndex = testTable.rows.length - 1; it('returns a datatable with the last N rows of the context', () => { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js index f45ec981b1a8a8..38b0d1bff606e8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/functions/common/timefilter.test.js @@ -15,7 +15,7 @@ const errors = getFunctionErrors().timefilter; let clock = null; -beforeEach(function () { +beforeEach(async function () { clock = sinon.useFakeTimers(); }); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/__snapshots__/repeat_image.stories.storyshot b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/__snapshots__/repeat_image.stories.storyshot index 9b97ae1fdacb32..5e6b8214c3c49b 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/__snapshots__/repeat_image.stories.storyshot +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/__snapshots__/repeat_image.stories.storyshot @@ -1,5 +1,18 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP +exports[`Storyshots enderers/repeatImage default 1`] = ` +
+ +
+`; + exports[`Storyshots renderers/repeatImage default 1`] = `
{ +const Renderer = ({ elasticLogo }: { elasticLogo: string }) => { const config = { type: 'image' as 'image', mode: 'cover', @@ -19,4 +20,10 @@ storiesOf('renderers/image', module).add('default', () => { }; return ; -}); +}; + +storiesOf('renderers/image', module).add( + 'default', + (_, props) => , + { decorators: [waitFor(getElasticLogo())] } +); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/repeat_image.stories.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/repeat_image.stories.tsx index ed2706389d83d1..0052b9139aae7f 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/repeat_image.stories.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/__stories__/repeat_image.stories.tsx @@ -8,13 +8,20 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { repeatImage } from '../repeat_image'; -import { Render } from './render'; import { - elasticLogo, - elasticOutline, + getElasticLogo, + getElasticOutline, } from '../../../../../../src/plugins/presentation_util/common/lib'; +import { waitFor } from '../../../../../../src/plugins/presentation_util/public/__stories__'; +import { Render } from './render'; -storiesOf('renderers/repeatImage', module).add('default', () => { +const Renderer = ({ + elasticLogo, + elasticOutline, +}: { + elasticLogo: string; + elasticOutline: string; +}) => { const config = { count: 42, image: elasticLogo, @@ -24,4 +31,12 @@ storiesOf('renderers/repeatImage', module).add('default', () => { }; return ; -}); +}; + +storiesOf('enderers/repeatImage', module).add( + 'default', + (_, props) => ( + + ), + { decorators: [waitFor(getElasticLogo()), waitFor(getElasticOutline())] } +); diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/image.tsx b/x-pack/plugins/canvas/canvas_plugin_src/renderers/image.tsx index 86e9daed105db2..78e3ecb7a4c952 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/image.tsx +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/image.tsx @@ -7,7 +7,10 @@ import ReactDOM from 'react-dom'; import React from 'react'; -import { elasticLogo, isValidUrl } from '../../../../../src/plugins/presentation_util/common/lib'; +import { + getElasticLogo, + isValidUrl, +} from '../../../../../src/plugins/presentation_util/common/lib'; import { Return as Arguments } from '../functions/common/image'; import { RendererStrings } from '../../i18n'; import { RendererFactory } from '../../types'; @@ -19,7 +22,8 @@ export const image: RendererFactory = () => ({ displayName: strings.getDisplayName(), help: strings.getHelpDescription(), reuseDomNode: true, - render(domNode, config, handlers) { + render: async (domNode, config, handlers) => { + const { elasticLogo } = await getElasticLogo(); const dataurl = isValidUrl(config.dataurl) ? config.dataurl : elasticLogo; const style = { diff --git a/x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.ts b/x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.ts index 149a8876834132..b7a94c2089d8c2 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.ts +++ b/x-pack/plugins/canvas/canvas_plugin_src/renderers/repeat_image.ts @@ -8,7 +8,7 @@ import $ from 'jquery'; import { times } from 'lodash'; import { - elasticOutline, + getElasticOutline, isValidUrl, } from '../../../../../src/plugins/presentation_util/common/lib'; import { RendererStrings, ErrorStrings } from '../../i18n'; @@ -23,10 +23,14 @@ export const repeatImage: RendererFactory = () => ({ displayName: strings.getDisplayName(), help: strings.getHelpDescription(), reuseDomNode: true, - render(domNode, config, handlers) { + render: async (domNode, config, handlers) => { + let image = config.image; + if (!isValidUrl(config.image)) { + image = (await getElasticOutline()).elasticOutline; + } const settings = { ...config, - image: isValidUrl(config.image) ? config.image : elasticOutline, + image, emptyImage: config.emptyImage || '', }; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js index 480d8ea364c427..4597826c031af8 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/arguments/image_upload/index.js @@ -12,7 +12,7 @@ import { get } from 'lodash'; import { AssetPicker } from '../../../../public/components/asset_picker'; import { encode, - elasticOutline, + getElasticOutline, isValidHttpUrl, resolveFromArgs, } from '../../../../../../../src/plugins/presentation_util/public'; @@ -168,13 +168,16 @@ class ImageUpload extends React.Component { } } -export const imageUpload = () => ({ - name: 'imageUpload', - displayName: strings.getDisplayName(), - help: strings.getHelp(), - resolveArgValue: true, - template: templateFromReactComponent(ImageUpload), - resolve({ args }) { - return { dataurl: resolveFromArgs(args, elasticOutline) }; - }, -}); +export const imageUpload = () => { + return { + name: 'imageUpload', + displayName: strings.getDisplayName(), + help: strings.getHelp(), + resolveArgValue: true, + template: templateFromReactComponent(ImageUpload), + resolve: async ({ args }) => { + const { elasticOutline } = await getElasticOutline(); + return { dataurl: resolveFromArgs(args, elasticOutline) }; + }, + }; +}; diff --git a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js index f974667b7fad99..c3855ad31e3f5e 100644 --- a/x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js +++ b/x-pack/plugins/canvas/canvas_plugin_src/uis/views/image.js @@ -6,38 +6,41 @@ */ import { - elasticLogo, + getElasticLogo, resolveFromArgs, } from '../../../../../../src/plugins/presentation_util/common/lib'; import { ViewStrings } from '../../../i18n'; const { Image: strings } = ViewStrings; -export const image = () => ({ - name: 'image', - displayName: strings.getDisplayName(), - modelArgs: [], - requiresContext: false, - args: [ - { - name: 'dataurl', - argType: 'imageUpload', - resolve({ args }) { - return { dataurl: resolveFromArgs(args, elasticLogo) }; +export const image = () => { + return { + name: 'image', + displayName: strings.getDisplayName(), + modelArgs: [], + requiresContext: false, + args: [ + { + name: 'dataurl', + argType: 'imageUpload', + resolve: async ({ args }) => { + const { elasticLogo } = await getElasticLogo(); + return { dataurl: resolveFromArgs(args, elasticLogo) }; + }, }, - }, - { - name: 'mode', - displayName: strings.getModeDisplayName(), - help: strings.getModeHelp(), - argType: 'select', - options: { - choices: [ - { value: 'contain', name: strings.getContainMode() }, - { value: 'cover', name: strings.getCoverMode() }, - { value: 'stretch', name: strings.getStretchMode() }, - ], + { + name: 'mode', + displayName: strings.getModeDisplayName(), + help: strings.getModeHelp(), + argType: 'select', + options: { + choices: [ + { value: 'contain', name: strings.getContainMode() }, + { value: 'cover', name: strings.getCoverMode() }, + { value: 'stretch', name: strings.getStretchMode() }, + ], + }, }, - }, - ], -}); + ], + }; +}; diff --git a/x-pack/plugins/canvas/i18n/constants.ts b/x-pack/plugins/canvas/i18n/constants.ts index 74646e140a20ad..2f192fd3e2d57b 100644 --- a/x-pack/plugins/canvas/i18n/constants.ts +++ b/x-pack/plugins/canvas/i18n/constants.ts @@ -51,3 +51,6 @@ export const TYPE_STRING = '`string`'; export const URL = 'URL'; export const UTC = 'UTC'; export const ZIP = 'ZIP'; +export const IMAGE_MODE_CONTAIN = 'contain'; +export const IMAGE_MODE_COVER = 'cover'; +export const IMAGE_MODE_STRETCH = 'stretch'; diff --git a/x-pack/plugins/canvas/i18n/functions/dict/image.ts b/x-pack/plugins/canvas/i18n/functions/dict/image.ts index 5e643cf8de6ee0..b619d550f9efd7 100644 --- a/x-pack/plugins/canvas/i18n/functions/dict/image.ts +++ b/x-pack/plugins/canvas/i18n/functions/dict/image.ts @@ -6,10 +6,16 @@ */ import { i18n } from '@kbn/i18n'; -import { image, ImageMode } from '../../../canvas_plugin_src/functions/common/image'; +import { image } from '../../../canvas_plugin_src/functions/common/image'; import { FunctionHelp } from '../function_help'; import { FunctionFactory } from '../../../types'; -import { URL, BASE64 } from '../../constants'; +import { + URL, + BASE64, + IMAGE_MODE_CONTAIN, + IMAGE_MODE_COVER, + IMAGE_MODE_STRETCH, +} from '../../constants'; export const help: FunctionHelp> = { help: i18n.translate('xpack.canvas.functions.imageHelpText', { @@ -35,9 +41,9 @@ export const help: FunctionHelp> = { '{cover} fills the container with the image, cropping from the sides or bottom as needed. ' + '{stretch} resizes the height and width of the image to 100% of the container.', values: { - contain: `\`"${ImageMode.CONTAIN}"\``, - cover: `\`"${ImageMode.COVER}"\``, - stretch: `\`"${ImageMode.STRETCH}"\``, + contain: `\`"${IMAGE_MODE_CONTAIN}"\``, + cover: `\`"${IMAGE_MODE_COVER}"\``, + stretch: `\`"${IMAGE_MODE_STRETCH}"\``, }, }), }, @@ -49,9 +55,9 @@ export const errors = { i18n.translate('xpack.canvas.functions.image.invalidImageModeErrorMessage', { defaultMessage: '"mode" must be "{contain}", "{cover}", or "{stretch}"', values: { - contain: ImageMode.CONTAIN, - cover: ImageMode.COVER, - stretch: ImageMode.STRETCH, + contain: IMAGE_MODE_CONTAIN, + cover: IMAGE_MODE_COVER, + stretch: IMAGE_MODE_STRETCH, }, }) ), diff --git a/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/custom_element_modal.stories.tsx b/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/custom_element_modal.stories.tsx index 93574270757f6d..a072579be2e826 100644 --- a/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/custom_element_modal.stories.tsx +++ b/x-pack/plugins/canvas/public/components/custom_element_modal/__stories__/custom_element_modal.stories.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { CustomElementModal } from '../custom_element_modal'; -import { elasticLogo } from '../../../../../../../src/plugins/presentation_util/public'; +import { waitFor } from '../../../../../../../src/plugins/presentation_util/public/__stories__'; +import { getElasticLogo } from '../../../../../../../src/plugins/presentation_util/public'; storiesOf('components/Elements/CustomElementModal', module) .add('with title', () => ( @@ -36,11 +37,15 @@ storiesOf('components/Elements/CustomElementModal', module) onSave={action('onSave')} /> )) - .add('with image', () => ( - - )); + .add( + 'with image', + (_, props) => ( + + ), + { decorators: [waitFor(getElasticLogo())] } + ); diff --git a/x-pack/plugins/canvas/public/components/element_card/__stories__/element_card.stories.tsx b/x-pack/plugins/canvas/public/components/element_card/__stories__/element_card.stories.tsx index 4c68f185b196f0..74cd86c8d17ddf 100644 --- a/x-pack/plugins/canvas/public/components/element_card/__stories__/element_card.stories.tsx +++ b/x-pack/plugins/canvas/public/components/element_card/__stories__/element_card.stories.tsx @@ -9,7 +9,8 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; import { ElementCard } from '../element_card'; -import { elasticLogo } from '../../../../../../../src/plugins/presentation_util/public'; +import { waitFor } from '../../../../../../../src/plugins/presentation_util/public/__stories__'; +import { getElasticLogo } from '../../../../../../../src/plugins/presentation_util/public'; storiesOf('components/Elements/ElementCard', module) .addDecorator((story) => ( @@ -27,13 +28,17 @@ storiesOf('components/Elements/ElementCard', module) description="Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis." /> )) - .add('with image', () => ( - - )) + .add( + 'with image', + (_, props) => ( + + ), + { decorators: [waitFor(getElasticLogo())] } + ) .add('with tags', () => ( = ({ functionRegistry }) => { const functionDefinitions = Object.values(functionRegistry); const copyDocs = () => { - copy(generateFunctionReference(functionDefinitions)); + const functionRefs = generateFunctionReference(functionDefinitions); + copy(functionRefs); notifyService.success( `Please paste updated docs into '/kibana/docs/canvas/canvas-function-reference.asciidoc' and commit your changes.`, { title: 'Copied function docs to clipboard' } diff --git a/x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.tsx b/x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.tsx index 3c68afb2bceca7..f267b48028f7d0 100644 --- a/x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.tsx +++ b/x-pack/plugins/canvas/public/components/render_with_fn/render_with_fn.tsx @@ -104,7 +104,7 @@ export const RenderWithFn: FC = ({ try { render(); firstRender.current = false; - } catch (err) { + } catch (err: any) { onError(err, { title: strings.getRenderErrorMessage(functionName) }); } }, [domNode, functionName, onError, render, resetRenderTarget, reuseNode]); diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/element_grid.stories.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/element_grid.stories.tsx index 769078da972f21..3f0611479c3b55 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/element_grid.stories.tsx +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/element_grid.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; +import { waitFor } from '../../../../../../../src/plugins/presentation_util/public/__stories__'; import { ElementGrid } from '../element_grid'; -import { testCustomElements } from './fixtures/test_elements'; +import { getTestCustomElements } from './fixtures/test_elements'; storiesOf('components/SavedElementsModal/ElementGrid', module) .addDecorator((story) => ( @@ -21,20 +22,28 @@ storiesOf('components/SavedElementsModal/ElementGrid', module) {story()}
)) - .add('default', () => ( - - )) - .add('with text filter', () => ( - - )); + .add( + 'default', + (_, props) => ( + + ), + { decorators: [waitFor(getTestCustomElements())] } + ) + .add( + 'with text filter', + (_, props) => ( + + ), + { decorators: [waitFor(getTestCustomElements())] } + ); diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/fixtures/test_elements.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/fixtures/test_elements.tsx index ef48b9815062c0..854bf9c685ad90 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/fixtures/test_elements.tsx +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/fixtures/test_elements.tsx @@ -5,32 +5,36 @@ * 2.0. */ -import { elasticLogo } from '../../../../../../../../src/plugins/presentation_util/public'; +import { getElasticLogo } from '../../../../../../../../src/plugins/presentation_util/public'; -export const testCustomElements = [ - { - id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5', - name: 'customElement1', - displayName: 'Custom Element 1', - help: 'sample description', - image: elasticLogo, - content: `{\"selectedNodes\":[{\"id\":\"element-3383b40a-de5d-4efb-8719-f4d8cffbfa74\",\"position\":{\"left\":142,\"top\":146,\"width\":700,\"height\":300,\"angle\":0,\"parent\":null,\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| pointseries x=\\\"project\\\" y=\\\"sum(price)\\\" color=\\\"state\\\" size=\\\"size(username)\\\"\\n| plot defaultStyle={seriesStyle points=5 fill=1}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"pointseries\",\"arguments\":{\"x\":[\"project\"],\"y\":[\"sum(price)\"],\"color\":[\"state\"],\"size\":[\"size(username)\"]}},{\"type\":\"function\",\"function\":\"plot\",\"arguments\":{\"defaultStyle\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"seriesStyle\",\"arguments\":{\"points\":[5],\"fill\":[1]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, - { - id: 'custom-element-b22d8d10-6116-46fb-9b46-c3f3340d3aaa', - name: 'customElement2', - displayName: 'Custom Element 2', - help: 'Aenean eu justo auctor, placerat felis non, scelerisque dolor. ', - image: elasticLogo, - content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, - { - id: 'custom-element-', - name: 'customElement3', - displayName: 'Custom Element 3', - help: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.', - image: elasticLogo, - content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, -]; +export const getTestCustomElements = async () => { + const { elasticLogo } = await getElasticLogo(); + const testCustomElements = [ + { + id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5', + name: 'customElement1', + displayName: 'Custom Element 1', + help: 'sample description', + image: elasticLogo, + content: `{\"selectedNodes\":[{\"id\":\"element-3383b40a-de5d-4efb-8719-f4d8cffbfa74\",\"position\":{\"left\":142,\"top\":146,\"width\":700,\"height\":300,\"angle\":0,\"parent\":null,\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| pointseries x=\\\"project\\\" y=\\\"sum(price)\\\" color=\\\"state\\\" size=\\\"size(username)\\\"\\n| plot defaultStyle={seriesStyle points=5 fill=1}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"pointseries\",\"arguments\":{\"x\":[\"project\"],\"y\":[\"sum(price)\"],\"color\":[\"state\"],\"size\":[\"size(username)\"]}},{\"type\":\"function\",\"function\":\"plot\",\"arguments\":{\"defaultStyle\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"seriesStyle\",\"arguments\":{\"points\":[5],\"fill\":[1]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + { + id: 'custom-element-b22d8d10-6116-46fb-9b46-c3f3340d3aaa', + name: 'customElement2', + displayName: 'Custom Element 2', + help: 'Aenean eu justo auctor, placerat felis non, scelerisque dolor. ', + image: elasticLogo, + content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + { + id: 'custom-element-', + name: 'customElement3', + displayName: 'Custom Element 3', + help: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.', + image: elasticLogo, + content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + ]; + return { testCustomElements }; +}; diff --git a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/saved_elements_modal.stories.tsx b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/saved_elements_modal.stories.tsx index d5c9af6ded8dff..086a4be1402118 100644 --- a/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/saved_elements_modal.stories.tsx +++ b/x-pack/plugins/canvas/public/components/saved_elements_modal/__stories__/saved_elements_modal.stories.tsx @@ -8,8 +8,9 @@ import React from 'react'; import { storiesOf } from '@storybook/react'; import { action } from '@storybook/addon-actions'; +import { waitFor } from '../../../../../../../src/plugins/presentation_util/public/__stories__'; import { SavedElementsModal } from '../saved_elements_modal.component'; -import { testCustomElements } from './fixtures/test_elements'; +import { getTestCustomElements } from './fixtures/test_elements'; import { CustomElement } from '../../../../types'; storiesOf('components/SavedElementsModal', module) @@ -25,27 +26,35 @@ storiesOf('components/SavedElementsModal', module) removeCustomElement={action('removeCustomElement')} /> )) - .add('with custom elements', () => ( - - )) - .add('with text filter', () => ( - - )); + .add( + 'with custom elements', + (_, props) => ( + + ), + { decorators: [waitFor(getTestCustomElements())] } + ) + .add( + 'with text filter', + (_, props) => ( + + ), + { decorators: [waitFor(getTestCustomElements())] } + ); diff --git a/x-pack/plugins/canvas/public/functions/pie.test.js b/x-pack/plugins/canvas/public/functions/pie.test.js index 5e35cc3bf523ce..f1ce8786f2c669 100644 --- a/x-pack/plugins/canvas/public/functions/pie.test.js +++ b/x-pack/plugins/canvas/public/functions/pie.test.js @@ -30,9 +30,9 @@ describe('pie', () => { }); describe('data', () => { - const result = fn(testPie).value.data; - it('has one series per unique label', () => { + const result = fn(testPie).value.data; + const uniqueLabels = testPie.rows.reduce( (unique, series) => !unique.includes(series.color) ? unique.concat([series.color]) : unique, @@ -44,6 +44,8 @@ describe('pie', () => { }); it('populates the data of the plot with points from the pointseries', () => { + const result = fn(testPie).value.data; + expect(result[0].data).toEqual([202]); expect(result[1].data).toEqual([67]); expect(result[2].data).toEqual([311]); diff --git a/x-pack/plugins/canvas/public/functions/plot.test.js b/x-pack/plugins/canvas/public/functions/plot.test.js index 8dd2470ea17dcb..a2eef889aa07ee 100644 --- a/x-pack/plugins/canvas/public/functions/plot.test.js +++ b/x-pack/plugins/canvas/public/functions/plot.test.js @@ -33,12 +33,15 @@ describe('plot', () => { }); describe('data', () => { - const result = fn(testPlot).value.data; it('is sorted by the series labels', () => { + const result = fn(testPlot).value.data; + expect(result.every((val, i) => (!!i ? val.label >= result[i - 1].label : true))).toBe(true); }); it('has one series per unique label', () => { + const result = fn(testPlot).value.data; + const uniqueLabels = testPlot.rows .reduce( (unique, series) => @@ -52,6 +55,8 @@ describe('plot', () => { }); it('populates the data of the plot with points from the pointseries', () => { + const result = fn(testPlot).value.data; + expect(result[0].data).toEqual([ [1517842800950, 605, { size: 100, text: 605 }], [1517929200950, 583, { size: 200, text: 583 }], @@ -118,6 +123,7 @@ describe('plot', () => { describe('palette', () => { it('sets the color palette', () => { const mockedColors = jest.fn(() => ['#FFFFFF', '#888888', '#000000']); + const mockedFn = functionWrapper( plotFunctionFactory({ get: () => ({ diff --git a/x-pack/plugins/canvas/public/lib/monaco_language_def.ts b/x-pack/plugins/canvas/public/lib/monaco_language_def.ts index f370ab7a9943f5..12dc385a4147fe 100644 --- a/x-pack/plugins/canvas/public/lib/monaco_language_def.ts +++ b/x-pack/plugins/canvas/public/lib/monaco_language_def.ts @@ -97,7 +97,6 @@ export const language: Language = { export function registerLanguage(functions: ExpressionFunction[]) { language.keywords = functions.map((fn) => fn.name); - monaco.languages.register({ id: LANGUAGE_ID }); monaco.languages.setMonarchTokensProvider(LANGUAGE_ID, language); } diff --git a/x-pack/plugins/canvas/public/plugin_api.ts b/x-pack/plugins/canvas/public/plugin_api.ts index 8f39f2d990d0ca..55a7390437c2bb 100644 --- a/x-pack/plugins/canvas/public/plugin_api.ts +++ b/x-pack/plugins/canvas/public/plugin_api.ts @@ -22,7 +22,9 @@ export interface CanvasApi { addArgumentUIs: AddToRegistry; addDatasourceUIs: AddToRegistry; addElements: AddToRegistry; - addFunctions: AddSpecsToRegistry<() => AnyExpressionFunctionDefinition>; + addFunctions: AddSpecsToRegistry< + (() => AnyExpressionFunctionDefinition) | AnyExpressionFunctionDefinition + >; addModelUIs: AddToRegistry; addRenderers: AddSpecsToRegistry; addTagUIs: AddToRegistry; diff --git a/x-pack/plugins/canvas/public/services/legacy/expressions.ts b/x-pack/plugins/canvas/public/services/legacy/expressions.ts index 99915cad745e3e..b48172172e3c73 100644 --- a/x-pack/plugins/canvas/public/services/legacy/expressions.ts +++ b/x-pack/plugins/canvas/public/services/legacy/expressions.ts @@ -42,6 +42,7 @@ export const expressionsServiceFactory: CanvasServiceFactory return batchedFunction({ functionName, args, context: serialize(input) }); }, }); + expressions.registerFunction(fn); }); })(); diff --git a/x-pack/plugins/canvas/public/services/legacy/stubs/expressions.ts b/x-pack/plugins/canvas/public/services/legacy/stubs/expressions.ts index bd1076ab0bf807..1093bb74521331 100644 --- a/x-pack/plugins/canvas/public/services/legacy/stubs/expressions.ts +++ b/x-pack/plugins/canvas/public/services/legacy/stubs/expressions.ts @@ -17,7 +17,9 @@ const setup = expressionsPlugin.setup(placeholder); export const expressionsService: ExpressionsService = setup.fork(); -functionDefinitions.forEach((fn) => expressionsService.registerFunction(fn)); -renderFunctions.forEach((fn) => { - expressionsService.registerRenderer((fn as unknown) as AnyExpressionRenderDefinition); -}); +export function setupExpressionsService() { + functionDefinitions.forEach((fn) => expressionsService.registerFunction(fn)); + renderFunctions.forEach((fn) => { + expressionsService.registerRenderer((fn as unknown) as AnyExpressionRenderDefinition); + }); +} diff --git a/x-pack/plugins/canvas/storybook/storyshots.test.tsx b/x-pack/plugins/canvas/storybook/storyshots.test.tsx index ddb52a22d2f17a..643bd1dc22041d 100644 --- a/x-pack/plugins/canvas/storybook/storyshots.test.tsx +++ b/x-pack/plugins/canvas/storybook/storyshots.test.tsx @@ -122,7 +122,6 @@ const converter = new Stories2SnapsConverter(); initStoryshots({ configPath: path.resolve(__dirname), framework: 'react', - // test: multiSnapshotWithOptions({}), asyncJest: true, test: async ({ story, context, done }) => { const renderer = create(createElement(story.render)); diff --git a/x-pack/plugins/canvas/tasks/mocks/customElementService.js b/x-pack/plugins/canvas/tasks/mocks/customElementService.js index 93625b32849ebd..596d57af97d1ef 100644 --- a/x-pack/plugins/canvas/tasks/mocks/customElementService.js +++ b/x-pack/plugins/canvas/tasks/mocks/customElementService.js @@ -5,33 +5,36 @@ * 2.0. */ -export const testCustomElements = [ - { - id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5', - name: 'customElement1', - displayName: 'Custom Element 1', - help: 'sample description', - image: '', - content: `{\"selectedNodes\":[{\"id\":\"element-3383b40a-de5d-4efb-8719-f4d8cffbfa74\",\"position\":{\"left\":142,\"top\":146,\"width\":700,\"height\":300,\"angle\":0,\"parent\":null,\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| pointseries x=\\\"project\\\" y=\\\"sum(price)\\\" color=\\\"state\\\" size=\\\"size(username)\\\"\\n| plot defaultStyle={seriesStyle points=5 fill=1}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"pointseries\",\"arguments\":{\"x\":[\"project\"],\"y\":[\"sum(price)\"],\"color\":[\"state\"],\"size\":[\"size(username)\"]}},{\"type\":\"function\",\"function\":\"plot\",\"arguments\":{\"defaultStyle\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"seriesStyle\",\"arguments\":{\"points\":[5],\"fill\":[1]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, - { - id: 'custom-element-b22d8d10-6116-46fb-9b46-c3f3340d3aaa', - name: 'customElement2', - displayName: 'Custom Element 2', - help: 'Aenean eu justo auctor, placerat felis non, scelerisque dolor. ', - image: '', - content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, - { - id: 'custom-element-', - name: 'customElement3', - displayName: 'Custom Element 3', - help: - 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.', - image: '', - content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, - }, -]; +export const getTestCustomElements = () => { + const testCustomElements = [ + { + id: 'custom-element-10d625f5-1342-47c9-8f19-d174ea6b65d5', + name: 'customElement1', + displayName: 'Custom Element 1', + help: 'sample description', + image: '', + content: `{\"selectedNodes\":[{\"id\":\"element-3383b40a-de5d-4efb-8719-f4d8cffbfa74\",\"position\":{\"left\":142,\"top\":146,\"width\":700,\"height\":300,\"angle\":0,\"parent\":null,\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| pointseries x=\\\"project\\\" y=\\\"sum(price)\\\" color=\\\"state\\\" size=\\\"size(username)\\\"\\n| plot defaultStyle={seriesStyle points=5 fill=1}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"pointseries\",\"arguments\":{\"x\":[\"project\"],\"y\":[\"sum(price)\"],\"color\":[\"state\"],\"size\":[\"size(username)\"]}},{\"type\":\"function\",\"function\":\"plot\",\"arguments\":{\"defaultStyle\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"seriesStyle\",\"arguments\":{\"points\":[5],\"fill\":[1]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + { + id: 'custom-element-b22d8d10-6116-46fb-9b46-c3f3340d3aaa', + name: 'customElement2', + displayName: 'Custom Element 2', + help: 'Aenean eu justo auctor, placerat felis non, scelerisque dolor. ', + image: '', + content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + { + id: 'custom-element-', + name: 'customElement3', + displayName: 'Custom Element 3', + help: + 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce lobortis aliquet arcu ut turpis duis.', + image: '', + content: `{\"selectedNodes\":[{\"id\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"position\":{\"left\":250,\"top\":119,\"width\":340,\"height\":517,\"angle\":0,\"parent\":null,\"type\":\"group\"},\"expression\":\"shape fill=\\\"rgba(255,255,255,0)\\\" | render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"shape\",\"arguments\":{\"fill\":[\"rgba(255,255,255,0)\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-e2c658ee-7614-4d92-a46e-2b1a81a24485\",\"position\":{\"left\":250,\"top\":405,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"## Jane Doe\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"## Jane Doe\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-3d16765e-5251-4954-8e2a-6c64ed465b73\",\"position\":{\"left\":250,\"top\":480,\"width\":340,\"height\":75,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\\"### Developer\\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render css=\\\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\\\"\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"### Developer\"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{\"css\":[\".canvasRenderEl h3 {\\ncolor: #444444;\\n}\"]}}]}},{\"id\":\"element-624675cf-46e9-4545-b86a-5409bbe53ac1\",\"position\":{\"left\":250,\"top\":555,\"width\":340,\"height\":81,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"filters\\n| demodata\\n| markdown \\n \\\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \\\" \\n font={font family=\\\"'Open Sans', Helvetica, Arial, sans-serif\\\" size=14 align=\\\"center\\\" color=\\\"#000000\\\" weight=\\\"normal\\\" underline=false italic=false}\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"filters\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"demodata\",\"arguments\":{}},{\"type\":\"function\",\"function\":\"markdown\",\"arguments\":{\"_\":[\"Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec vel sollicitudin mauris, ut scelerisque urna. \"],\"font\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"font\",\"arguments\":{\"family\":[\"'Open Sans', Helvetica, Arial, sans-serif\"],\"size\":[14],\"align\":[\"center\"],\"color\":[\"#000000\"],\"weight\":[\"normal\"],\"underline\":[false],\"italic\":[false]}}]}]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}},{\"id\":\"element-c2916246-26dd-4c65-91c6-d1ad3f1791ee\",\"position\":{\"left\":293,\"top\":119,\"width\":254,\"height\":252,\"angle\":0,\"parent\":\"group-dccf4ed7-1593-49a0-9902-caf4d4a4b7f5\",\"type\":\"element\"},\"expression\":\"image dataurl={asset \\\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\\\"} mode=\\\"contain\\\"\\n| render\",\"ast\":{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"image\",\"arguments\":{\"dataurl\":[{\"type\":\"expression\",\"chain\":[{\"type\":\"function\",\"function\":\"asset\",\"arguments\":{\"_\":[\"asset-0c6f377f-771e-432e-8e2e-15c3e9142ad6\"]}}]}],\"mode\":[\"contain\"]}},{\"type\":\"function\",\"function\":\"render\",\"arguments\":{}}]}}]}`, + }, + ]; + return { testCustomElements }; +}; export const create = () => {}; diff --git a/x-pack/plugins/canvas/types/functions.ts b/x-pack/plugins/canvas/types/functions.ts index 70521a061a8bb8..2569e0b10685b7 100644 --- a/x-pack/plugins/canvas/types/functions.ts +++ b/x-pack/plugins/canvas/types/functions.ts @@ -6,6 +6,7 @@ */ import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common'; +import { UnwrapPromiseOrReturn } from '@kbn/utility-types'; import { functions as commonFunctions } from '../canvas_plugin_src/functions/common'; import { functions as browserFunctions } from '../canvas_plugin_src/functions/browser'; import { functions as serverFunctions } from '../canvas_plugin_src/functions/server'; @@ -72,7 +73,7 @@ import { initFunctions } from '../public/functions'; */ // prettier-ignore export type ExpressionFunctionFactory = - () => ExpressionFunctionDefinition; + () => ExpressionFunctionDefinition /** * `FunctionFactory` exists as a name shim between the `ExpressionFunction` type and @@ -81,9 +82,9 @@ export type ExpressionFunctionFactory = +export type FunctionFactory = FnFactory extends ExpressionFunctionFactory ? - ExpressionFunctionDefinition : + ExpressionFunctionDefinition> : never; type CommonFunction = FunctionFactory;