* [Canvas] Expression repeat image (#104255) * Repeat Image plugin added. # Conflicts: # packages/kbn-optimizer/limits.yml # x-pack/plugins/translations/translations/ja-JP.json # x-pack/plugins/translations/translations/zh-CN.json * Removed not defined plugin `userSetup`.
This commit is contained in:
parent
f276d0732a
commit
17933a559c
|
@ -18,6 +18,7 @@
|
|||
"devTools": "src/plugins/dev_tools",
|
||||
"expressions": "src/plugins/expressions",
|
||||
"expressionError": "src/plugins/expression_error",
|
||||
"expressionRepeatImage": "src/plugins/expression_repeat_image",
|
||||
"expressionRevealImage": "src/plugins/expression_reveal_image",
|
||||
"expressionShape": "src/plugins/expression_shape",
|
||||
"inputControl": "src/plugins/input_control_vis",
|
||||
|
|
|
@ -74,6 +74,10 @@ This API doesn't support angular, for registering angular dev tools, bootstrap a
|
|||
|Expression Error plugin adds an error renderer to the expression plugin. The renderer will display the error image.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/expression_repeat_image/README.md[expressionRepeatImage]
|
||||
|Expression Repeat Image plugin adds a repeatImage function to the expression plugin and an associated renderer. The renderer will display the given image in mutliple instances.
|
||||
|
||||
|
||||
|{kib-repo}blob/{branch}/src/plugins/expression_reveal_image/README.md[expressionRevealImage]
|
||||
|Expression Reveal Image plugin adds a revealImage function to the expression plugin and an associated renderer. The renderer will display the given percentage of a given image.
|
||||
|
||||
|
|
|
@ -113,4 +113,5 @@ pageLoadAssetSize:
|
|||
expressionRevealImage: 25675
|
||||
cases: 144442
|
||||
expressionError: 22127
|
||||
expressionRepeatImage: 22341
|
||||
expressionShape: 30033
|
||||
|
|
|
@ -18,6 +18,7 @@ export const storybookAliases = {
|
|||
data_enhanced: 'x-pack/plugins/data_enhanced/.storybook',
|
||||
embeddable: 'src/plugins/embeddable/.storybook',
|
||||
expression_error: 'src/plugins/expression_error/.storybook',
|
||||
expression_repeat_image: 'src/plugins/expression_repeat_image/.storybook',
|
||||
expression_reveal_image: 'src/plugins/expression_reveal_image/.storybook',
|
||||
expression_shape: 'src/plugins/expression_shape/.storybook',
|
||||
infra: 'x-pack/plugins/infra/.storybook',
|
||||
|
|
|
@ -12,6 +12,12 @@ import { i18n } from '@kbn/i18n';
|
|||
import { get } from 'lodash';
|
||||
import { ShowDebugging } from './show_debugging';
|
||||
|
||||
export interface Props {
|
||||
payload: {
|
||||
error: Error;
|
||||
};
|
||||
}
|
||||
|
||||
const strings = {
|
||||
getDescription: () =>
|
||||
i18n.translate('expressionError.errorComponent.description', {
|
||||
|
@ -23,12 +29,6 @@ const strings = {
|
|||
}),
|
||||
};
|
||||
|
||||
export interface Props {
|
||||
payload: {
|
||||
error: Error;
|
||||
};
|
||||
}
|
||||
|
||||
export const Error: FC<Props> = ({ payload }) => {
|
||||
const message = get(payload, 'error.message');
|
||||
|
||||
|
|
10
src/plugins/expression_repeat_image/.storybook/main.js
Normal file
10
src/plugins/expression_repeat_image/.storybook/main.js
Normal file
|
@ -0,0 +1,10 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
// eslint-disable-next-line import/no-commonjs
|
||||
module.exports = require('@kbn/storybook').defaultConfig;
|
9
src/plugins/expression_repeat_image/README.md
Executable file
9
src/plugins/expression_repeat_image/README.md
Executable file
|
@ -0,0 +1,9 @@
|
|||
# expressionRepeatImage
|
||||
|
||||
Expression Repeat Image plugin adds a `repeatImage` function to the expression plugin and an associated renderer. The renderer will display the given image in mutliple instances.
|
||||
|
||||
---
|
||||
|
||||
## Development
|
||||
|
||||
See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment.
|
14
src/plugins/expression_repeat_image/common/constants.ts
Normal file
14
src/plugins/expression_repeat_image/common/constants.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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 PLUGIN_ID = 'expressionRepeatImage';
|
||||
export const PLUGIN_NAME = 'expressionRepeatImage';
|
||||
|
||||
export const CONTEXT = '_context_';
|
||||
export const BASE64 = '`base64`';
|
||||
export const URL = 'URL';
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { repeatImageFunction } from './repeat_image_function';
|
||||
|
||||
export const functions = [repeatImageFunction];
|
||||
|
||||
export { repeatImageFunction };
|
|
@ -1,29 +1,31 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* 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 { ExecutionContext } from 'src/plugins/expressions';
|
||||
import {
|
||||
getElasticLogo,
|
||||
getElasticOutline,
|
||||
functionWrapper,
|
||||
} from '../../../../../../src/plugins/presentation_util/common/lib';
|
||||
import { repeatImage } from './repeat_image';
|
||||
} from '../../../presentation_util/common/lib';
|
||||
import { repeatImageFunction } from './repeat_image_function';
|
||||
|
||||
describe('repeatImage', () => {
|
||||
const fn = functionWrapper(repeatImage);
|
||||
const fn = functionWrapper(repeatImageFunction);
|
||||
|
||||
let elasticLogo;
|
||||
let elasticOutline;
|
||||
let elasticLogo: string;
|
||||
let elasticOutline: string;
|
||||
beforeEach(async () => {
|
||||
elasticLogo = await (await getElasticLogo()).elasticLogo;
|
||||
elasticOutline = await (await getElasticOutline()).elasticOutline;
|
||||
});
|
||||
|
||||
it('returns a render as repeatImage', async () => {
|
||||
const result = await fn(10);
|
||||
const result = await fn(10, {}, {} as ExecutionContext);
|
||||
expect(result).toHaveProperty('type', 'render');
|
||||
expect(result).toHaveProperty('as', 'repeatImage');
|
||||
});
|
||||
|
@ -31,46 +33,47 @@ describe('repeatImage', () => {
|
|||
describe('args', () => {
|
||||
describe('image', () => {
|
||||
it('sets the source of the repeated image', async () => {
|
||||
const result = (await fn(10, { image: elasticLogo })).value;
|
||||
const result = (await fn(10, { image: elasticLogo }, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('image', elasticLogo);
|
||||
});
|
||||
|
||||
it('defaults to the Elastic outline logo', async () => {
|
||||
const result = (await fn(100000)).value;
|
||||
const result = (await fn(100000, {}, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('image', elasticOutline);
|
||||
});
|
||||
});
|
||||
|
||||
describe('size', () => {
|
||||
it('sets the size of the image', async () => {
|
||||
const result = (await fn(-5, { size: 200 })).value;
|
||||
const result = (await fn(-5, { size: 200 }, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('size', 200);
|
||||
});
|
||||
|
||||
it('defaults to 100', async () => {
|
||||
const result = (await fn(-5)).value;
|
||||
const result = (await fn(-5, {}, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('size', 100);
|
||||
});
|
||||
});
|
||||
|
||||
describe('max', () => {
|
||||
it('sets the maximum number of a times the image is repeated', async () => {
|
||||
const result = (await fn(100000, { max: 20 })).value;
|
||||
const result = (await fn(100000, { max: 20 }, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('max', 20);
|
||||
});
|
||||
it('defaults to 1000', async () => {
|
||||
const result = (await fn(100000)).value;
|
||||
const result = (await fn(100000, {}, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('max', 1000);
|
||||
});
|
||||
});
|
||||
|
||||
describe('emptyImage', () => {
|
||||
it('returns repeatImage object with emptyImage as undefined', async () => {
|
||||
const result = (await fn(100000, { emptyImage: elasticLogo })).value;
|
||||
const result = (await fn(100000, { emptyImage: elasticLogo }, {} as ExecutionContext))
|
||||
.value;
|
||||
expect(result).toHaveProperty('emptyImage', elasticLogo);
|
||||
});
|
||||
it('sets emptyImage to null', async () => {
|
||||
const result = (await fn(100000)).value;
|
||||
const result = (await fn(100000, {}, {} as ExecutionContext)).value;
|
||||
expect(result).toHaveProperty('emptyImage', null);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* 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 {
|
||||
getElasticOutline,
|
||||
isValidUrl,
|
||||
resolveWithMissingImage,
|
||||
} from '../../../presentation_util/common/lib';
|
||||
import { CONTEXT, BASE64, URL } from '../constants';
|
||||
import { ExpressionRepeatImageFunction } from '../types';
|
||||
|
||||
export const strings = {
|
||||
help: i18n.translate('expressionRepeatImage.functions.repeatImageHelpText', {
|
||||
defaultMessage: 'Configures a repeating image element.',
|
||||
}),
|
||||
args: {
|
||||
emptyImage: i18n.translate(
|
||||
'expressionRepeatImage.functions.repeatImage.args.emptyImageHelpText',
|
||||
{
|
||||
defaultMessage:
|
||||
'Fills the difference between the {CONTEXT} and {maxArg} parameter for the element with this image. ' +
|
||||
'Provide an image asset as a {BASE64} data {URL}, or pass in a sub-expression.',
|
||||
values: {
|
||||
BASE64,
|
||||
CONTEXT,
|
||||
maxArg: '`max`',
|
||||
URL,
|
||||
},
|
||||
}
|
||||
),
|
||||
image: i18n.translate('expressionRepeatImage.functions.repeatImage.args.imageHelpText', {
|
||||
defaultMessage:
|
||||
'The image to repeat. Provide an image asset as a {BASE64} data {URL}, or pass in a sub-expression.',
|
||||
values: {
|
||||
BASE64,
|
||||
URL,
|
||||
},
|
||||
}),
|
||||
max: i18n.translate('expressionRepeatImage.functions.repeatImage.args.maxHelpText', {
|
||||
defaultMessage: 'The maximum number of times the image can repeat.',
|
||||
}),
|
||||
size: i18n.translate('expressionRepeatImage.functions.repeatImage.args.sizeHelpText', {
|
||||
defaultMessage:
|
||||
'The maximum height or width of the image, in pixels. ' +
|
||||
'When the image is taller than it is wide, this function limits the height.',
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
const errors = {
|
||||
getMissingMaxArgumentErrorMessage: () =>
|
||||
i18n.translate('expressionRepeatImage.error.repeatImage.missingMaxArgument', {
|
||||
defaultMessage: '{maxArgument} must be set if providing an {emptyImageArgument}',
|
||||
values: {
|
||||
maxArgument: '`max`',
|
||||
emptyImageArgument: '`emptyImage`',
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
export const repeatImageFunction: ExpressionRepeatImageFunction = () => {
|
||||
const { help, args: argHelp } = strings;
|
||||
|
||||
return {
|
||||
name: 'repeatImage',
|
||||
aliases: [],
|
||||
type: 'render',
|
||||
inputTypes: ['number'],
|
||||
help,
|
||||
args: {
|
||||
emptyImage: {
|
||||
types: ['string', 'null'],
|
||||
help: argHelp.emptyImage,
|
||||
default: null,
|
||||
},
|
||||
image: {
|
||||
types: ['string', 'null'],
|
||||
help: argHelp.image,
|
||||
default: null,
|
||||
},
|
||||
max: {
|
||||
types: ['number', 'null'],
|
||||
help: argHelp.max,
|
||||
default: 1000,
|
||||
},
|
||||
size: {
|
||||
types: ['number'],
|
||||
default: 100,
|
||||
help: argHelp.size,
|
||||
},
|
||||
},
|
||||
fn: async (count, args) => {
|
||||
if (args.emptyImage !== null && isValidUrl(args.emptyImage) && args.max === null) {
|
||||
throw new Error(errors.getMissingMaxArgumentErrorMessage());
|
||||
}
|
||||
const { elasticOutline } = await getElasticOutline();
|
||||
return {
|
||||
type: 'render',
|
||||
as: 'repeatImage',
|
||||
value: {
|
||||
count: Math.floor(count),
|
||||
...args,
|
||||
image: resolveWithMissingImage(args.image, elasticOutline),
|
||||
emptyImage: resolveWithMissingImage(args.emptyImage),
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
};
|
11
src/plugins/expression_repeat_image/common/index.ts
Executable file
11
src/plugins/expression_repeat_image/common/index.ts
Executable file
|
@ -0,0 +1,11 @@
|
|||
/*
|
||||
* 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 './constants';
|
||||
export * from './types';
|
||||
export * from './expression_functions';
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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 { ExpressionFunctionDefinition, ExpressionValueRender } from '../../../expressions';
|
||||
|
||||
interface Arguments {
|
||||
image: string | null;
|
||||
size: number;
|
||||
max: number | null;
|
||||
emptyImage: string | null;
|
||||
}
|
||||
|
||||
export interface Return {
|
||||
count: number;
|
||||
image: string;
|
||||
size: number;
|
||||
max: number;
|
||||
emptyImage: string | null;
|
||||
}
|
||||
|
||||
export type ExpressionRepeatImageFunction = () => ExpressionFunctionDefinition<
|
||||
'repeatImage',
|
||||
number,
|
||||
Arguments,
|
||||
Promise<ExpressionValueRender<Arguments>>
|
||||
>;
|
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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 type OriginString = 'bottom' | 'left' | 'top' | 'right';
|
||||
export interface RepeatImageRendererConfig {
|
||||
max: number;
|
||||
count: number;
|
||||
emptyImage: string;
|
||||
image: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface NodeDimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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';
|
13
src/plugins/expression_repeat_image/jest.config.js
Normal file
13
src/plugins/expression_repeat_image/jest.config.js
Normal file
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
preset: '@kbn/test',
|
||||
rootDir: '../../..',
|
||||
roots: ['<rootDir>/src/plugins/expression_repeat_image'],
|
||||
};
|
10
src/plugins/expression_repeat_image/kibana.json
Executable file
10
src/plugins/expression_repeat_image/kibana.json
Executable file
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "expressionRepeatImage",
|
||||
"version": "1.0.0",
|
||||
"kibanaVersion": "kibana",
|
||||
"server": true,
|
||||
"ui": true,
|
||||
"requiredPlugins": ["expressions", "presentationUtil"],
|
||||
"optionalPlugins": [],
|
||||
"requiredBundles": []
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
/*
|
||||
* 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 './repeat_image_component';
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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, { ReactElement, useEffect, useState } from 'react';
|
||||
import { times } from 'lodash';
|
||||
import { IInterpreterRenderHandlers } from 'src/plugins/expressions';
|
||||
import { RepeatImageRendererConfig } from '../../common';
|
||||
|
||||
interface RepeatImageComponentProps extends RepeatImageRendererConfig {
|
||||
onLoaded: IInterpreterRenderHandlers['done'];
|
||||
parentNode: HTMLElement;
|
||||
}
|
||||
|
||||
interface LoadedImages {
|
||||
image: HTMLImageElement | null;
|
||||
emptyImage: HTMLImageElement | null;
|
||||
}
|
||||
|
||||
async function loadImage(src: string): Promise<HTMLImageElement> {
|
||||
return new Promise((resolve, reject) => {
|
||||
const img = new Image();
|
||||
img.onload = () => resolve(img);
|
||||
img.onerror = (error) => reject(error);
|
||||
img.src = src;
|
||||
});
|
||||
}
|
||||
|
||||
async function loadImages(images: string[]): Promise<Array<HTMLImageElement | null>> {
|
||||
const results = await Promise.allSettled([...images.map(loadImage)]);
|
||||
return results.map((loadedImage) =>
|
||||
loadedImage.status === 'rejected' ? null : loadedImage.value
|
||||
);
|
||||
}
|
||||
|
||||
function setImageSize(img: HTMLImageElement, size: number) {
|
||||
if (img.naturalHeight > img.naturalWidth) {
|
||||
img.height = size;
|
||||
} else {
|
||||
img.width = size;
|
||||
}
|
||||
}
|
||||
|
||||
function createImageJSX(img: HTMLImageElement | null) {
|
||||
if (!img) return null;
|
||||
const params = img.width > img.height ? { heigth: img.height } : { width: img.width };
|
||||
return <img src={img.src} {...params} alt="" />;
|
||||
}
|
||||
|
||||
function RepeatImageComponent({
|
||||
max,
|
||||
count,
|
||||
emptyImage: emptyImageSrc,
|
||||
image: imageSrc,
|
||||
size,
|
||||
onLoaded,
|
||||
}: RepeatImageComponentProps) {
|
||||
const [images, setImages] = useState<LoadedImages>({
|
||||
image: null,
|
||||
emptyImage: null,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
loadImages([imageSrc, emptyImageSrc]).then((result) => {
|
||||
const [image, emptyImage] = result;
|
||||
setImages({ image, emptyImage });
|
||||
onLoaded();
|
||||
});
|
||||
}, [imageSrc, emptyImageSrc, onLoaded]);
|
||||
|
||||
const imagesToRender: Array<ReactElement | null> = [];
|
||||
|
||||
const { image, emptyImage } = images;
|
||||
|
||||
if (max && count > max) count = max;
|
||||
|
||||
if (image) {
|
||||
setImageSize(image, size);
|
||||
times(count, () => imagesToRender.push(createImageJSX(image)));
|
||||
}
|
||||
|
||||
if (emptyImage) {
|
||||
setImageSize(emptyImage, size);
|
||||
times(max - count, () => imagesToRender.push(createImageJSX(emptyImage)));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="repeatImage" style={{ pointerEvents: 'none' }}>
|
||||
{imagesToRender}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
// default export required for React.Lazy
|
||||
// eslint-disable-next-line import/no-default-export
|
||||
export { RepeatImageComponent as default };
|
|
@ -1,19 +1,20 @@
|
|||
/*
|
||||
* 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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
* 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 from 'react';
|
||||
import { storiesOf } from '@storybook/react';
|
||||
import { repeatImage } from '../repeat_image';
|
||||
import { Render } from '../../../../presentation_util/public/__stories__';
|
||||
import { repeatImageRenderer } from '../repeat_image_renderer';
|
||||
import {
|
||||
getElasticLogo,
|
||||
getElasticOutline,
|
||||
} from '../../../../../../src/plugins/presentation_util/common/lib';
|
||||
import { waitFor } from '../../../../../../src/plugins/presentation_util/public/__stories__';
|
||||
import { Render } from './render';
|
||||
|
||||
const Renderer = ({
|
||||
elasticLogo,
|
||||
|
@ -30,7 +31,7 @@ const Renderer = ({
|
|||
emptyImage: elasticOutline,
|
||||
};
|
||||
|
||||
return <Render renderer={repeatImage} config={config} width="400px" />;
|
||||
return <Render renderer={repeatImageRenderer} config={config} width="400px" />;
|
||||
};
|
||||
|
||||
storiesOf('enderers/repeatImage', module).add(
|
|
@ -0,0 +1,13 @@
|
|||
/*
|
||||
* 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 { repeatImageRenderer } from './repeat_image_renderer';
|
||||
|
||||
export const renderers = [repeatImageRenderer];
|
||||
|
||||
export { repeatImageRenderer };
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* 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, { 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 { getElasticOutline, isValidUrl, withSuspense } from '../../../presentation_util/public';
|
||||
import { RepeatImageRendererConfig } from '../../common/types';
|
||||
|
||||
const strings = {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('expressionRepeatImage.renderer.repeatImage.displayName', {
|
||||
defaultMessage: 'RepeatImage',
|
||||
}),
|
||||
getHelpDescription: () =>
|
||||
i18n.translate('expressionRepeatImage.renderer.repeatImage.helpDescription', {
|
||||
defaultMessage: 'Render a basic repeatImage',
|
||||
}),
|
||||
};
|
||||
|
||||
const LazyRepeatImageComponent = lazy(() => import('../components/repeat_image_component'));
|
||||
const RepeatImageComponent = withSuspense(LazyRepeatImageComponent, null);
|
||||
|
||||
export const repeatImageRenderer = (): ExpressionRenderDefinition<RepeatImageRendererConfig> => ({
|
||||
name: 'repeatImage',
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render: async (
|
||||
domNode: HTMLElement,
|
||||
config: RepeatImageRendererConfig,
|
||||
handlers: IInterpreterRenderHandlers
|
||||
) => {
|
||||
const { elasticOutline } = await getElasticOutline();
|
||||
const settings = {
|
||||
...config,
|
||||
image: isValidUrl(config.image) ? config.image : elasticOutline,
|
||||
emptyImage: config.emptyImage || '',
|
||||
};
|
||||
|
||||
handlers.onDestroy(() => {
|
||||
unmountComponentAtNode(domNode);
|
||||
});
|
||||
|
||||
render(
|
||||
<I18nProvider>
|
||||
<RepeatImageComponent onLoaded={handlers.done} {...settings} parentNode={domNode} />
|
||||
</I18nProvider>,
|
||||
domNode
|
||||
);
|
||||
},
|
||||
});
|
17
src/plugins/expression_repeat_image/public/index.ts
Executable file
17
src/plugins/expression_repeat_image/public/index.ts
Executable file
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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 { ExpressionRepeatImagePlugin } from './plugin';
|
||||
|
||||
export type { ExpressionRepeatImagePluginSetup, ExpressionRepeatImagePluginStart } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new ExpressionRepeatImagePlugin();
|
||||
}
|
||||
|
||||
export * from './expression_renderers';
|
41
src/plugins/expression_repeat_image/public/plugin.ts
Executable file
41
src/plugins/expression_repeat_image/public/plugin.ts
Executable file
|
@ -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 { CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
||||
import { ExpressionsStart, ExpressionsSetup } from '../../expressions/public';
|
||||
import { repeatImageFunction } from '../common/expression_functions';
|
||||
import { repeatImageRenderer } from './expression_renderers';
|
||||
|
||||
interface SetupDeps {
|
||||
expressions: ExpressionsSetup;
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
expression: ExpressionsStart;
|
||||
}
|
||||
|
||||
export type ExpressionRepeatImagePluginSetup = void;
|
||||
export type ExpressionRepeatImagePluginStart = void;
|
||||
|
||||
export class ExpressionRepeatImagePlugin
|
||||
implements
|
||||
Plugin<
|
||||
ExpressionRepeatImagePluginSetup,
|
||||
ExpressionRepeatImagePluginStart,
|
||||
SetupDeps,
|
||||
StartDeps
|
||||
> {
|
||||
public setup(core: CoreSetup, { expressions }: SetupDeps): ExpressionRepeatImagePluginSetup {
|
||||
expressions.registerFunction(repeatImageFunction);
|
||||
expressions.registerRenderer(repeatImageRenderer);
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ExpressionRepeatImagePluginStart {}
|
||||
|
||||
public stop() {}
|
||||
}
|
15
src/plugins/expression_repeat_image/server/index.ts
Executable file
15
src/plugins/expression_repeat_image/server/index.ts
Executable file
|
@ -0,0 +1,15 @@
|
|||
/*
|
||||
* 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 { ExpressionRepeatImagePlugin } from './plugin';
|
||||
|
||||
export type { ExpressionRepeatImagePluginSetup, ExpressionRepeatImagePluginStart } from './plugin';
|
||||
|
||||
export function plugin() {
|
||||
return new ExpressionRepeatImagePlugin();
|
||||
}
|
39
src/plugins/expression_repeat_image/server/plugin.ts
Executable file
39
src/plugins/expression_repeat_image/server/plugin.ts
Executable file
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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 { CoreSetup, CoreStart, Plugin } from '../../../core/public';
|
||||
import { ExpressionsServerStart, ExpressionsServerSetup } from '../../expressions/server';
|
||||
import { repeatImageFunction } from '../common';
|
||||
|
||||
interface SetupDeps {
|
||||
expressions: ExpressionsServerSetup;
|
||||
}
|
||||
|
||||
interface StartDeps {
|
||||
expression: ExpressionsServerStart;
|
||||
}
|
||||
|
||||
export type ExpressionRepeatImagePluginSetup = void;
|
||||
export type ExpressionRepeatImagePluginStart = void;
|
||||
|
||||
export class ExpressionRepeatImagePlugin
|
||||
implements
|
||||
Plugin<
|
||||
ExpressionRepeatImagePluginSetup,
|
||||
ExpressionRepeatImagePluginStart,
|
||||
SetupDeps,
|
||||
StartDeps
|
||||
> {
|
||||
public setup(core: CoreSetup, { expressions }: SetupDeps): ExpressionRepeatImagePluginSetup {
|
||||
expressions.registerFunction(repeatImageFunction);
|
||||
}
|
||||
|
||||
public start(core: CoreStart): ExpressionRepeatImagePluginStart {}
|
||||
|
||||
public stop() {}
|
||||
}
|
21
src/plugins/expression_repeat_image/tsconfig.json
Normal file
21
src/plugins/expression_repeat_image/tsconfig.json
Normal file
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"extends": "../../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"composite": true,
|
||||
"outDir": "./target/types",
|
||||
"emitDeclarationOnly": true,
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"isolatedModules": true
|
||||
},
|
||||
"include": [
|
||||
"common/**/*",
|
||||
"public/**/*",
|
||||
"server/**/*",
|
||||
],
|
||||
"references": [
|
||||
{ "path": "../../core/tsconfig.json" },
|
||||
{ "path": "../presentation_util/tsconfig.json" },
|
||||
{ "path": "../expressions/tsconfig.json" },
|
||||
]
|
||||
}
|
|
@ -42,7 +42,6 @@ import { render } from './render';
|
|||
import { replace } from './replace';
|
||||
import { rounddate } from './rounddate';
|
||||
import { rowCount } from './rowCount';
|
||||
import { repeatImage } from './repeat_image';
|
||||
import { seriesStyle } from './seriesStyle';
|
||||
import { sort } from './sort';
|
||||
import { staticColumn } from './staticColumn';
|
||||
|
@ -90,7 +89,6 @@ export const functions = [
|
|||
ply,
|
||||
progress,
|
||||
render,
|
||||
repeatImage,
|
||||
replace,
|
||||
rounddate,
|
||||
rowCount,
|
||||
|
|
|
@ -1,84 +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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { ExpressionFunctionDefinition } from 'src/plugins/expressions/common';
|
||||
import {
|
||||
getElasticOutline,
|
||||
resolveWithMissingImage,
|
||||
} from '../../../../../../src/plugins/presentation_util/common/lib';
|
||||
import { Render } from '../../../types';
|
||||
import { getFunctionHelp } from '../../../i18n';
|
||||
|
||||
interface Arguments {
|
||||
image: string | null;
|
||||
size: number;
|
||||
max: number;
|
||||
emptyImage: string | null;
|
||||
}
|
||||
|
||||
export interface Return {
|
||||
count: number;
|
||||
image: string;
|
||||
size: number;
|
||||
max: number;
|
||||
emptyImage: string | null;
|
||||
}
|
||||
|
||||
export function repeatImage(): ExpressionFunctionDefinition<
|
||||
'repeatImage',
|
||||
number,
|
||||
Arguments,
|
||||
Promise<Render<Arguments>>
|
||||
> {
|
||||
const { help, args: argHelp } = getFunctionHelp().repeatImage;
|
||||
return {
|
||||
name: 'repeatImage',
|
||||
aliases: [],
|
||||
type: 'render',
|
||||
inputTypes: ['number'],
|
||||
help,
|
||||
args: {
|
||||
emptyImage: {
|
||||
types: ['string', 'null'],
|
||||
help: argHelp.emptyImage,
|
||||
default: null,
|
||||
},
|
||||
image: {
|
||||
types: ['string', 'null'],
|
||||
help: argHelp.image,
|
||||
default: null,
|
||||
},
|
||||
max: {
|
||||
types: ['number'],
|
||||
help: argHelp.max,
|
||||
default: 1000,
|
||||
},
|
||||
size: {
|
||||
types: ['number'],
|
||||
default: 100,
|
||||
help: argHelp.size,
|
||||
},
|
||||
},
|
||||
fn: async (count, args) => {
|
||||
const { elasticOutline } = await getElasticOutline();
|
||||
if (args.image === null) {
|
||||
args.image = elasticOutline;
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'render',
|
||||
as: 'repeatImage',
|
||||
value: {
|
||||
count: Math.floor(count),
|
||||
...args,
|
||||
image: resolveWithMissingImage(args.image, elasticOutline),
|
||||
emptyImage: resolveWithMissingImage(args.emptyImage),
|
||||
},
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
|
@ -11,20 +11,9 @@ import { metric } from './metric';
|
|||
import { pie } from './pie';
|
||||
import { plot } from './plot';
|
||||
import { progress } from './progress';
|
||||
import { repeatImage } from './repeat_image';
|
||||
import { table } from './table';
|
||||
import { text } from './text';
|
||||
import { table } from './table';
|
||||
|
||||
export const renderFunctions = [
|
||||
image,
|
||||
markdown,
|
||||
metric,
|
||||
pie,
|
||||
plot,
|
||||
progress,
|
||||
repeatImage,
|
||||
table,
|
||||
text,
|
||||
];
|
||||
export const renderFunctions = [image, markdown, metric, pie, plot, progress, table, text];
|
||||
|
||||
export const renderFunctionFactories = [];
|
||||
|
|
|
@ -5,9 +5,17 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { revealImageRenderer } from '../../../../../src/plugins/expression_reveal_image/public';
|
||||
import { errorRenderer, debugRenderer } from '../../../../../src/plugins/expression_error/public';
|
||||
import { repeatImageRenderer } from '../../../../../src/plugins/expression_repeat_image/public';
|
||||
import { revealImageRenderer } from '../../../../../src/plugins/expression_reveal_image/public';
|
||||
import { shapeRenderer } from '../../../../../src/plugins/expression_shape/public';
|
||||
|
||||
export const renderFunctions = [revealImageRenderer, debugRenderer, errorRenderer, shapeRenderer];
|
||||
export const renderFunctions = [
|
||||
revealImageRenderer,
|
||||
debugRenderer,
|
||||
errorRenderer,
|
||||
shapeRenderer,
|
||||
repeatImageRenderer,
|
||||
];
|
||||
|
||||
export const renderFunctionFactories = [];
|
||||
|
|
|
@ -1,79 +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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import $ from 'jquery';
|
||||
import { times } from 'lodash';
|
||||
import {
|
||||
getElasticOutline,
|
||||
isValidUrl,
|
||||
} from '../../../../../src/plugins/presentation_util/common/lib';
|
||||
import { RendererStrings, ErrorStrings } from '../../i18n';
|
||||
import { Return as Arguments } from '../functions/common/repeat_image';
|
||||
import { RendererFactory } from '../../types';
|
||||
|
||||
const { repeatImage: strings } = RendererStrings;
|
||||
const { RepeatImage: errors } = ErrorStrings;
|
||||
|
||||
export const repeatImage: RendererFactory<Arguments> = () => ({
|
||||
name: 'repeatImage',
|
||||
displayName: strings.getDisplayName(),
|
||||
help: strings.getHelpDescription(),
|
||||
reuseDomNode: true,
|
||||
render: async (domNode, config, handlers) => {
|
||||
let image = config.image;
|
||||
if (!isValidUrl(config.image)) {
|
||||
image = (await getElasticOutline()).elasticOutline;
|
||||
}
|
||||
const settings = {
|
||||
...config,
|
||||
image,
|
||||
emptyImage: config.emptyImage || '',
|
||||
};
|
||||
|
||||
const container = $('<div class="repeatImage" style="pointer-events: none;">');
|
||||
|
||||
function setSize(img: HTMLImageElement) {
|
||||
if (img.naturalHeight > img.naturalWidth) {
|
||||
img.height = settings.size;
|
||||
} else {
|
||||
img.width = settings.size;
|
||||
}
|
||||
}
|
||||
|
||||
function finish() {
|
||||
$(domNode).append(container);
|
||||
handlers.done();
|
||||
}
|
||||
|
||||
const img = new Image();
|
||||
img.onload = function () {
|
||||
setSize(img);
|
||||
if (settings.max && settings.count > settings.max) {
|
||||
settings.count = settings.max;
|
||||
}
|
||||
times(settings.count, () => container.append($(img).clone()));
|
||||
|
||||
if (isValidUrl(settings.emptyImage)) {
|
||||
if (settings.max == null) {
|
||||
throw new Error(errors.getMissingMaxArgumentErrorMessage());
|
||||
}
|
||||
|
||||
const emptyImage = new Image();
|
||||
emptyImage.onload = function () {
|
||||
setSize(emptyImage);
|
||||
times(settings.max - settings.count, () => container.append($(emptyImage).clone()));
|
||||
finish();
|
||||
};
|
||||
emptyImage.src = settings.emptyImage;
|
||||
} else {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
|
||||
img.src = settings.image;
|
||||
},
|
||||
});
|
|
@ -14,18 +14,20 @@ import { ArgumentStrings } from '../../../i18n';
|
|||
|
||||
const { Shape: strings } = ArgumentStrings;
|
||||
|
||||
const ShapeArgInput = ({ onValueChange, argValue, typeInstance }) => (
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<ShapePickerPopover
|
||||
value={argValue}
|
||||
onChange={onValueChange}
|
||||
shapes={typeInstance.options.shapes}
|
||||
ariaLabel={typeInstance.displayName}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
const ShapeArgInput = ({ onValueChange, argValue, typeInstance }) => {
|
||||
return (
|
||||
<EuiFlexGroup gutterSize="s">
|
||||
<EuiFlexItem grow={false}>
|
||||
<ShapePickerPopover
|
||||
value={argValue}
|
||||
onChange={onValueChange}
|
||||
shapes={typeInstance.options.shapes}
|
||||
ariaLabel={typeInstance.displayName}
|
||||
/>
|
||||
</EuiFlexItem>
|
||||
</EuiFlexGroup>
|
||||
);
|
||||
};
|
||||
|
||||
ShapeArgInput.propTypes = {
|
||||
argValue: PropTypes.any.isRequired,
|
||||
|
|
|
@ -58,16 +58,6 @@ export const ErrorStrings = {
|
|||
},
|
||||
}),
|
||||
},
|
||||
RepeatImage: {
|
||||
getMissingMaxArgumentErrorMessage: () =>
|
||||
i18n.translate('xpack.canvas.error.repeatImage.missingMaxArgument', {
|
||||
defaultMessage: '{maxArgument} must be set if providing an {emptyImageArgument}',
|
||||
values: {
|
||||
maxArgument: '`max`',
|
||||
emptyImageArgument: '`emptyImage`',
|
||||
},
|
||||
}),
|
||||
},
|
||||
WorkpadDropzone: {
|
||||
getTooManyFilesErrorMessage: () =>
|
||||
i18n.translate('xpack.canvas.error.workpadDropzone.tooManyFilesErrorMessage', {
|
||||
|
|
|
@ -1,47 +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; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import { repeatImage } from '../../../canvas_plugin_src/functions/common/repeat_image';
|
||||
import { FunctionHelp } from '../function_help';
|
||||
import { FunctionFactory } from '../../../types';
|
||||
import { CONTEXT, BASE64, URL } from '../../constants';
|
||||
|
||||
export const help: FunctionHelp<FunctionFactory<typeof repeatImage>> = {
|
||||
help: i18n.translate('xpack.canvas.functions.repeatImageHelpText', {
|
||||
defaultMessage: 'Configures a repeating image element.',
|
||||
}),
|
||||
args: {
|
||||
emptyImage: i18n.translate('xpack.canvas.functions.repeatImage.args.emptyImageHelpText', {
|
||||
defaultMessage:
|
||||
'Fills the difference between the {CONTEXT} and {maxArg} parameter for the element with this image. ' +
|
||||
'Provide an image asset as a {BASE64} data {URL}, or pass in a sub-expression.',
|
||||
values: {
|
||||
BASE64,
|
||||
CONTEXT,
|
||||
maxArg: '`max`',
|
||||
URL,
|
||||
},
|
||||
}),
|
||||
image: i18n.translate('xpack.canvas.functions.repeatImage.args.imageHelpText', {
|
||||
defaultMessage:
|
||||
'The image to repeat. Provide an image asset as a {BASE64} data {URL}, or pass in a sub-expression.',
|
||||
values: {
|
||||
BASE64,
|
||||
URL,
|
||||
},
|
||||
}),
|
||||
max: i18n.translate('xpack.canvas.functions.repeatImage.args.maxHelpText', {
|
||||
defaultMessage: 'The maximum number of times the image can repeat.',
|
||||
}),
|
||||
size: i18n.translate('xpack.canvas.functions.repeatImage.args.sizeHelpText', {
|
||||
defaultMessage:
|
||||
'The maximum height or width of the image, in pixels. ' +
|
||||
'When the image is taller than it is wide, this function limits the height.',
|
||||
}),
|
||||
},
|
||||
};
|
|
@ -55,7 +55,6 @@ import { help as ply } from './dict/ply';
|
|||
import { help as pointseries } from './dict/pointseries';
|
||||
import { help as progress } from './dict/progress';
|
||||
import { help as render } from './dict/render';
|
||||
import { help as repeatImage } from './dict/repeat_image';
|
||||
import { help as replace } from './dict/replace';
|
||||
import { help as rounddate } from './dict/rounddate';
|
||||
import { help as rowCount } from './dict/row_count';
|
||||
|
@ -214,7 +213,6 @@ export const getFunctionHelp = (): FunctionHelpDict => ({
|
|||
pointseries,
|
||||
progress,
|
||||
render,
|
||||
repeatImage,
|
||||
replace,
|
||||
rounddate,
|
||||
rowCount,
|
||||
|
|
|
@ -119,16 +119,6 @@ export const RendererStrings = {
|
|||
defaultMessage: 'Render a progress indicator that reveals a percentage of an element',
|
||||
}),
|
||||
},
|
||||
repeatImage: {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('xpack.canvas.renderer.repeatImage.displayName', {
|
||||
defaultMessage: 'Image repeat',
|
||||
}),
|
||||
getHelpDescription: () =>
|
||||
i18n.translate('xpack.canvas.renderer.repeatImage.helpDescription', {
|
||||
defaultMessage: 'Repeat an image a given number of times',
|
||||
}),
|
||||
},
|
||||
table: {
|
||||
getDisplayName: () =>
|
||||
i18n.translate('xpack.canvas.renderer.table.displayName', {
|
||||
|
|
|
@ -11,9 +11,10 @@
|
|||
"data",
|
||||
"embeddable",
|
||||
"expressionError",
|
||||
"expressionRepeatImage",
|
||||
"expressionRevealImage",
|
||||
"expressions",
|
||||
"expressionShape",
|
||||
"expressions",
|
||||
"features",
|
||||
"inspector",
|
||||
"presentationUtil",
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import {
|
||||
EuiModal,
|
||||
EuiModalBody,
|
||||
|
@ -18,8 +19,6 @@ import {
|
|||
EuiSpacer,
|
||||
} from '@elastic/eui';
|
||||
import { FormattedMessage } from '@kbn/i18n/react';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
||||
import { withSuspense } from '../../../../../../../src/plugins/presentation_util/public';
|
||||
import { LazyErrorComponent } from '../../../../../../../src/plugins/expression_error/public';
|
||||
import { Datatable } from '../../datatable';
|
||||
|
|
|
@ -84,12 +84,12 @@ export const RenderWithFn: FC<Props> = ({
|
|||
[]
|
||||
);
|
||||
|
||||
const render = useCallback(() => {
|
||||
const render = useCallback(async () => {
|
||||
if (!isEqual(handlers.current, incomingHandlers)) {
|
||||
handlers.current = incomingHandlers;
|
||||
}
|
||||
|
||||
renderFn(renderTarget.current!, config, handlers.current);
|
||||
await renderFn(renderTarget.current!, config, handlers.current);
|
||||
}, [renderTarget, config, renderFn, incomingHandlers]);
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -101,12 +101,13 @@ export const RenderWithFn: FC<Props> = ({
|
|||
resetRenderTarget();
|
||||
}
|
||||
|
||||
try {
|
||||
render();
|
||||
firstRender.current = false;
|
||||
} catch (err: any) {
|
||||
onError(err, { title: strings.getRenderErrorMessage(functionName) });
|
||||
}
|
||||
render()
|
||||
.then(() => {
|
||||
firstRender.current = false;
|
||||
})
|
||||
.catch((err) => {
|
||||
onError(err, { title: strings.getRenderErrorMessage(functionName) });
|
||||
});
|
||||
}, [domNode, functionName, onError, render, resetRenderTarget, reuseNode]);
|
||||
|
||||
return (
|
||||
|
|
|
@ -18,7 +18,7 @@ interface Props {
|
|||
|
||||
export const ShapePicker: FC<Props> = ({ shapes, onChange = () => {} }) => (
|
||||
<EuiFlexGrid gutterSize="s" columns={4} className="canvasShapePicker">
|
||||
{shapes.sort().map((shapeKey) => (
|
||||
{shapes.sort().map((shapeKey: string) => (
|
||||
<EuiFlexItem key={shapeKey}>
|
||||
<EuiLink onClick={() => onChange(shapeKey)}>
|
||||
<ShapePreview shape={shapeKey} />
|
||||
|
|
|
@ -9,7 +9,6 @@ import React, { FC, RefCallback, useCallback, useState } from 'react';
|
|||
import PropTypes from 'prop-types';
|
||||
import {
|
||||
LazyShapeDrawer,
|
||||
Shape,
|
||||
ShapeDrawerComponentProps,
|
||||
getDefaultShapeData,
|
||||
SvgConfig,
|
||||
|
@ -19,7 +18,7 @@ import {
|
|||
import { withSuspense } from '../../../../../../src/plugins/presentation_util/public';
|
||||
|
||||
interface Props {
|
||||
shape?: Shape;
|
||||
shape?: string;
|
||||
}
|
||||
|
||||
const ShapeDrawer = withSuspense<ShapeDrawerComponentProps, ShapeRef>(LazyShapeDrawer);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
*/
|
||||
|
||||
import { image } from '../canvas_plugin_src/renderers/image';
|
||||
import { repeatImage } from '../canvas_plugin_src/renderers/repeat_image';
|
||||
import { markdown } from '../canvas_plugin_src/renderers/markdown';
|
||||
import { metric } from '../canvas_plugin_src/renderers/metric';
|
||||
import { pie } from '../canvas_plugin_src/renderers/pie';
|
||||
|
@ -14,11 +13,12 @@ import { plot } from '../canvas_plugin_src/renderers/plot';
|
|||
import { progress } from '../canvas_plugin_src/renderers/progress';
|
||||
import { table } from '../canvas_plugin_src/renderers/table';
|
||||
import { text } from '../canvas_plugin_src/renderers/text';
|
||||
import { revealImageRenderer as revealImage } from '../../../../src/plugins/expression_reveal_image/public';
|
||||
import {
|
||||
errorRenderer as error,
|
||||
debugRenderer as debug,
|
||||
} from '../../../../src/plugins/expression_error/public';
|
||||
import { repeatImageRenderer as repeatImage } from '../../../../src/plugins/expression_repeat_image/public';
|
||||
import { revealImageRenderer as revealImage } from '../../../../src/plugins/expression_reveal_image/public';
|
||||
import { shapeRenderer as shape } from '../../../../src/plugins/expression_shape/public';
|
||||
|
||||
/**
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
{ "path": "../../../src/plugins/embeddable/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expressions/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_error/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_repeat_image/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_reveal_image/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/expression_shape/tsconfig.json" },
|
||||
{ "path": "../../../src/plugins/home/tsconfig.json" },
|
||||
|
|
|
@ -6061,7 +6061,7 @@
|
|||
"xpack.canvas.error.esService.fieldsFetchErrorMessage": "「{index}」の Elasticsearch フィールドを取得できませんでした",
|
||||
"xpack.canvas.error.esService.indicesFetchErrorMessage": "Elasticsearch インデックスを取得できませんでした",
|
||||
"xpack.canvas.error.RenderWithFn.renderErrorMessage": "「{functionName}」のレンダリングが失敗しました",
|
||||
"xpack.canvas.error.repeatImage.missingMaxArgument": "{emptyImageArgument} を指定する場合は、{maxArgument} を設定する必要があります",
|
||||
"expressionRepeatImage.error.repeatImage.missingMaxArgument": "{emptyImageArgument} を指定する場合は、{maxArgument} を設定する必要があります",
|
||||
"xpack.canvas.error.useCloneWorkpad.cloneFailureErrorMessage": "ワークパッドのクローンを作成できませんでした",
|
||||
"xpack.canvas.error.useCreateWorkpad.uploadFailureErrorMessage": "ワークパッドをアップロードできませんでした",
|
||||
"xpack.canvas.error.useDeleteWorkpads.deleteFailureErrorMessage": "すべてのワークパッドを削除できませんでした",
|
||||
|
@ -6304,11 +6304,11 @@
|
|||
"xpack.canvas.functions.render.args.containerStyleHelpText": "背景、境界、透明度を含む、コンテナーのスタイルです。",
|
||||
"xpack.canvas.functions.render.args.cssHelpText": "このエレメントの対象となるカスタム {CSS} のブロックです。",
|
||||
"xpack.canvas.functions.renderHelpText": "{CONTEXT}を特定のエレメントとしてレンダリングし、背景と境界のスタイルなどのエレメントレベルのオプションを設定します。",
|
||||
"xpack.canvas.functions.repeatImage.args.emptyImageHelpText": "この画像のエレメントについて、{CONTEXT}および{maxArg}パラメーターの差異を解消します。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。",
|
||||
"xpack.canvas.functions.repeatImage.args.imageHelpText": "繰り返す画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。",
|
||||
"xpack.canvas.functions.repeatImage.args.maxHelpText": "画像が繰り返される最高回数です。",
|
||||
"xpack.canvas.functions.repeatImage.args.sizeHelpText": "画像の高さまたは幅のピクセル単位での最高値です。画像が縦長の場合、この関数は高さを制限します。",
|
||||
"xpack.canvas.functions.repeatImageHelpText": "繰り返し画像エレメントを構成します。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.emptyImageHelpText": "この画像のエレメントについて、{CONTEXT}および{maxArg}パラメーターの差異を解消します。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.imageHelpText": "繰り返す画像です。画像アセットは{BASE64}データ{URL}として提供するか、部分式で渡します。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.maxHelpText": "画像が繰り返される最高回数です。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.sizeHelpText": "画像の高さまたは幅のピクセル単位での最高値です。画像が縦長の場合、この関数は高さを制限します。",
|
||||
"expressionRepeatImage.functions.repeatImageHelpText": "繰り返し画像エレメントを構成します。",
|
||||
"xpack.canvas.functions.replace.args.flagsHelpText": "フラグを指定します。{url}を参照してください。",
|
||||
"xpack.canvas.functions.replace.args.patternHelpText": "{JS} 正規表現のテキストまたはパターンです。例:{example}。ここではキャプチャグループを使用できます。",
|
||||
"xpack.canvas.functions.replace.args.replacementHelpText": "文字列の一致する部分の代わりです。キャプチャグループはノードによってアクセス可能です。例:{example}。",
|
||||
|
@ -6505,8 +6505,8 @@
|
|||
"xpack.canvas.renderer.plot.helpDescription": "データから XY プロットをレンダリングします",
|
||||
"xpack.canvas.renderer.progress.displayName": "進捗インジケーター",
|
||||
"xpack.canvas.renderer.progress.helpDescription": "エレメントのパーセンテージを示す進捗インジケーターをレンダリングします",
|
||||
"xpack.canvas.renderer.repeatImage.displayName": "画像の繰り返し",
|
||||
"xpack.canvas.renderer.repeatImage.helpDescription": "画像を指定回数繰り返し表示します",
|
||||
"expressionRepeatImage.renderer.repeatImage.displayName": "画像の繰り返し",
|
||||
"expressionRepeatImage.renderer.repeatImage.helpDescription": "画像を指定回数繰り返し表示します",
|
||||
"expressionShape.renderer.shape.displayName": "形状",
|
||||
"expressionShape.renderer.shape.helpDescription": "基本的な図形をレンダリングします",
|
||||
"xpack.canvas.renderer.table.displayName": "データテーブル",
|
||||
|
|
|
@ -6097,7 +6097,7 @@
|
|||
"xpack.canvas.error.esService.fieldsFetchErrorMessage": "无法为“{index}”提取 Elasticsearch 字段",
|
||||
"xpack.canvas.error.esService.indicesFetchErrorMessage": "无法提取 Elasticsearch 索引",
|
||||
"xpack.canvas.error.RenderWithFn.renderErrorMessage": "呈现“{functionName}”失败。",
|
||||
"xpack.canvas.error.repeatImage.missingMaxArgument": "如果提供 {emptyImageArgument},则必须设置 {maxArgument}",
|
||||
"expressionRepeatImage.error.repeatImage.missingMaxArgument": "如果提供 {emptyImageArgument},则必须设置 {maxArgument}",
|
||||
"xpack.canvas.error.useCloneWorkpad.cloneFailureErrorMessage": "无法克隆 Workpad",
|
||||
"xpack.canvas.error.useCreateWorkpad.uploadFailureErrorMessage": "无法上传 Workpad",
|
||||
"xpack.canvas.error.useDeleteWorkpads.deleteFailureErrorMessage": "无法删除所有 Workpad",
|
||||
|
@ -6341,11 +6341,11 @@
|
|||
"xpack.canvas.functions.render.args.containerStyleHelpText": "容器的样式,包括背景、边框和透明度。",
|
||||
"xpack.canvas.functions.render.args.cssHelpText": "要限定于元素的任何定制 {CSS} 块。",
|
||||
"xpack.canvas.functions.renderHelpText": "将 {CONTEXT} 呈现为特定元素,并设置元素级别选项,例如背景和边框样式。",
|
||||
"xpack.canvas.functions.repeatImage.args.emptyImageHelpText": "使用此图像填充元素的 {CONTEXT} 和 {maxArg} 参数之间的差距。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。",
|
||||
"xpack.canvas.functions.repeatImage.args.imageHelpText": "要重复的图像。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。",
|
||||
"xpack.canvas.functions.repeatImage.args.maxHelpText": "图像可以重复的最大次数。",
|
||||
"xpack.canvas.functions.repeatImage.args.sizeHelpText": "图像的最大高度或宽度,以像素为单位。图像的高大于宽时,此函数将限制高度。",
|
||||
"xpack.canvas.functions.repeatImageHelpText": "配置重复图像元素。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.emptyImageHelpText": "使用此图像填充元素的 {CONTEXT} 和 {maxArg} 参数之间的差距。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.imageHelpText": "要重复的图像。以 {BASE64} 数据 {URL} 的形式提供图像资产或传入子表达式。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.maxHelpText": "图像可以重复的最大次数。",
|
||||
"expressionRepeatImage.functions.repeatImage.args.sizeHelpText": "图像的最大高度或宽度,以像素为单位。图像的高大于宽时,此函数将限制高度。",
|
||||
"expressionRepeatImage.functions.repeatImageHelpText": "配置重复图像元素。",
|
||||
"xpack.canvas.functions.replace.args.flagsHelpText": "指定标志。请参见 {url}。",
|
||||
"xpack.canvas.functions.replace.args.patternHelpText": "{JS} 正则表达式的文本或模式。例如,{example}。您可以在此处使用捕获组。",
|
||||
"xpack.canvas.functions.replace.args.replacementHelpText": "字符串匹配部分的替代。捕获组可以通过其索引进行访问。例如,{example}。",
|
||||
|
@ -6542,10 +6542,12 @@
|
|||
"xpack.canvas.renderer.plot.helpDescription": "根据您的数据呈现 XY 坐标图",
|
||||
"xpack.canvas.renderer.progress.displayName": "进度指示",
|
||||
"xpack.canvas.renderer.progress.helpDescription": "呈现显示元素百分比的进度指示",
|
||||
"xpack.canvas.renderer.repeatImage.displayName": "图像重复",
|
||||
"xpack.canvas.renderer.repeatImage.helpDescription": "重复图像给定次数",
|
||||
"expressionShape.renderer.shape.displayName": "形状",
|
||||
"expressionShape.renderer.shape.helpDescription": "呈现基本形状",
|
||||
"expressionRepeatImage.renderer.repeatImage.displayName": "图像重复",
|
||||
"expressionRepeatImage.renderer.repeatImage.helpDescription": "重复图像给定次数",
|
||||
"expressionRevealImage.renderer.revealImage.displayName": "图像显示",
|
||||
"expressionRevealImage.renderer.revealImage.helpDescription": "显示一定百分比的图像,以制作定制的仪表样式图表",
|
||||
"xpack.canvas.renderer.table.displayName": "数据表",
|
||||
"xpack.canvas.renderer.table.helpDescription": "将表格数据呈现为 {HTML}",
|
||||
"xpack.canvas.renderer.text.displayName": "纯文本",
|
||||
|
@ -7026,8 +7028,6 @@
|
|||
"expressionRevealImage.functions.revealImage.args.originHelpText": "要开始图像填充的位置。例如 {list} 或 {end}。",
|
||||
"expressionRevealImage.functions.revealImage.invalidPercentErrorMessage": "无效值:“{percent}”。百分比必须介于 0 和 1 之间",
|
||||
"expressionRevealImage.functions.revealImageHelpText": "配置图像显示元素。",
|
||||
"expressionRevealImage.renderer.revealImage.displayName": "图像显示",
|
||||
"expressionRevealImage.renderer.revealImage.helpDescription": "显示一定百分比的图像,以制作定制的仪表样式图表",
|
||||
"xpack.cases.connectors.cases.externalIncidentAdded": " (由 {user} 于 {date}添加) ",
|
||||
"xpack.cases.connectors.cases.externalIncidentCreated": " (由 {user} 于 {date}创建) ",
|
||||
"xpack.cases.connectors.cases.externalIncidentDefault": " (由 {user} 于 {date}创建) ",
|
||||
|
|
Loading…
Reference in a new issue