Skip to content

Commit

Permalink
Added expression_image plugin.
Browse files Browse the repository at this point in the history
  • Loading branch information
Kuznietsov committed Jul 23, 2021
1 parent 3e4b64b commit 64f00ea
Show file tree
Hide file tree
Showing 48 changed files with 543 additions and 264 deletions.
1 change: 1 addition & 0 deletions .i18nrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"devTools": "src/plugins/dev_tools",
"expressions": "src/plugins/expressions",
"expressionError": "src/plugins/expression_error",
"expressionImage": "src/plugins/expression_image",
"expressionRepeatImage": "src/plugins/expression_repeat_image",
"expressionRevealImage": "src/plugins/expression_reveal_image",
"expressionShape": "src/plugins/expression_shape",
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,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_image/README.md[expressionImage]
|Expression Image plugin adds an image renderer to the expression plugin. The renderer will display the given 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.
Expand Down
1 change: 1 addition & 0 deletions packages/kbn-optimizer/limits.yml
Original file line number Diff line number Diff line change
Expand Up @@ -114,5 +114,6 @@ pageLoadAssetSize:
cases: 144442
expressionError: 22127
expressionRepeatImage: 22341
expressionImage: 19288
expressionShape: 30033
userSetup: 18532
1 change: 1 addition & 0 deletions src/dev/storybook/aliases.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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_image: 'src/plugins/expression_image/.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',
Expand Down
10 changes: 10 additions & 0 deletions src/plugins/expression_image/.storybook/main.js
Original file line number Diff line number Diff line change
@@ -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 changes: 9 additions & 0 deletions src/plugins/expression_image/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# expressionRevealImage

Expression Image plugin adds an `image` renderer to the expression plugin. The renderer will display the given image.

---

## Development

See the [kibana contributing guide](https://github.com/elastic/kibana/blob/master/CONTRIBUTING.md) for instructions setting up your development environment.
14 changes: 14 additions & 0 deletions src/plugins/expression_image/common/constants.ts
Original file line number Diff line number Diff line change
@@ -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 = 'expressionImage';
export const PLUGIN_NAME = 'expressionImage';

export const CONTEXT = '_context_';
export const BASE64 = '`base64`';
export const URL = 'URL';
Original file line number Diff line number Diff line change
@@ -1,72 +1,78 @@
/*
* 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 expect from '@kbn/expect';
import { ExecutionContext } from 'src/plugins/expressions';
import {
functionWrapper,
getElasticLogo,
getElasticOutline,
functionWrapper,
} from '../../../../../../src/plugins/presentation_util/common/lib';
import { image } from './image';
} from '../../../presentation_util/common/lib';
import { imageFunction as image } from './image_function';

// TODO: the test was not running and is not up to date
describe('image', () => {
const fn = functionWrapper(image);

let elasticLogo;
let elasticOutline;
let elasticLogo: string;
let elasticOutline: string;

beforeEach(async () => {
elasticLogo = (await getElasticLogo()).elasticLogo;
elasticOutline = (await getElasticOutline()).elasticOutline;
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' });
const result = await fn(
null,
{ dataurl: elasticOutline, mode: 'cover' },
{} as ExecutionContext
);
expect(result).to.have.property('type', 'image');
});

describe('args', () => {
describe('dataurl', () => {
it('sets the source of the image using dataurl', async () => {
const result = await fn(null, { dataurl: elasticOutline });
const result = await fn(null, { dataurl: elasticOutline }, {} as ExecutionContext);
expect(result).to.have.property('dataurl', elasticOutline);
});

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 = await fn(null, { url: elasticOutline });
const result = await fn(null, { url: elasticOutline }, {} as ExecutionContext);
expect(result).to.have.property('dataurl', elasticOutline);
});

it('defaults to the elasticLogo if not provided', async () => {
const result = await fn(null);
const result = await fn(null, {}, {} as ExecutionContext);
expect(result).to.have.property('dataurl', elasticLogo);
});
});

describe('sets the mode', () => {
it('to contain', async () => {
const result = await fn(null, { mode: 'contain' });
const result = await fn(null, { mode: 'contain' }, {} as ExecutionContext);
expect(result).to.have.property('mode', 'contain');
});

it('to cover', async () => {
const result = await fn(null, { mode: 'cover' });
const result = await fn(null, { mode: 'cover' }, {} as ExecutionContext);
expect(result).to.have.property('mode', 'cover');
});

it('to stretch', async () => {
const result = await fn(null, { mode: 'stretch' });
const result = await fn(null, { mode: 'stretch' }, {} as ExecutionContext);
expect(result).to.have.property('mode', '100% 100%');
});

it("defaults to 'contain' if not provided", async () => {
const result = await fn(null);
const result = await fn(null, {}, {} as ExecutionContext);
expect(result).to.have.property('mode', 'contain');
});
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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 { getElasticLogo, resolveWithMissingImage } from '../../../presentation_util/common/lib';
import { BASE64, URL } from '../constants';
import { ExpressionImageFunction, ImageMode } from '../types';

export const strings = {
help: i18n.translate('expressionImage.functions.imageHelpText', {
defaultMessage:
'Displays an image. Provide an image asset as a {BASE64} data {URL}, or pass in a sub-expression.',
values: {
BASE64,
URL,
},
}),
args: {
dataurl: i18n.translate('expressionImage.functions.image.args.dataurlHelpText', {
defaultMessage: 'The {https} {URL} or {BASE64} data {URL} of an image.',
values: {
BASE64,
https: 'HTTP(S)',
URL,
},
}),
mode: i18n.translate('expressionImage.functions.image.args.modeHelpText', {
defaultMessage:
'{contain} shows the entire image, scaled to fit. ' +
'{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}"\``,
},
}),
},
};

const errors = {
invalidImageMode: () =>
i18n.translate('expressionImage.functions.image.invalidImageModeErrorMessage', {
defaultMessage: '"mode" must be "{contain}", "{cover}", or "{stretch}"',
values: {
contain: ImageMode.CONTAIN,
cover: ImageMode.COVER,
stretch: ImageMode.STRETCH,
},
}),
};

export const imageFunction: ExpressionImageFunction = () => {
const { help, args: argHelp } = strings;

return {
name: 'image',
aliases: [],
type: 'image',
inputTypes: ['null'],
help,
args: {
dataurl: {
// This was accepting dataurl, but there was no facility in fn for checking type and handling a dataurl type.
types: ['string', 'null'],
help: argHelp.dataurl,
aliases: ['_', 'url'],
default: null,
},
mode: {
types: ['string'],
help: argHelp.mode,
default: 'contain',
options: Object.values(ImageMode),
},
},
fn: async (input, { dataurl, mode }) => {
if (!mode || !Object.values(ImageMode).includes(mode)) {
throw new Error(errors.invalidImageMode());
}

const modeStyle = mode === 'stretch' ? '100% 100%' : mode;
const { elasticLogo } = await getElasticLogo();
return {
type: 'image',
mode: modeStyle,
dataurl: resolveWithMissingImage(dataurl, elasticLogo) as string,
};
},
};
};
13 changes: 13 additions & 0 deletions src/plugins/expression_image/common/expression_functions/index.ts
Original file line number Diff line number Diff line change
@@ -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 { imageFunction } from './image_function';

export const functions = [imageFunction];

export { imageFunction };
11 changes: 11 additions & 0 deletions src/plugins/expression_image/common/index.ts
Original file line number Diff line number Diff line change
@@ -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';
32 changes: 32 additions & 0 deletions src/plugins/expression_image/common/types/expression_functions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* 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 } from '../../../expressions';

export enum ImageMode {
CONTAIN = 'contain',
COVER = 'cover',
STRETCH = 'stretch',
}

interface Arguments {
dataurl: string | null;
mode: ImageMode | null;
}

export interface Return {
type: 'image';
mode: string;
dataurl: string;
}

export type ExpressionImageFunction = () => ExpressionFunctionDefinition<
'image',
null,
Arguments,
Promise<Return>
>;
21 changes: 21 additions & 0 deletions src/plugins/expression_image/common/types/expression_renderers.ts
Original file line number Diff line number Diff line change
@@ -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.
*/

import { ImageMode } from './expression_functions';

export type OriginString = 'bottom' | 'left' | 'top' | 'right';

export interface ImageRendererConfig {
dataurl: string | null;
mode: ImageMode | null;
}

export interface NodeDimensions {
width: number;
height: number;
}
9 changes: 9 additions & 0 deletions src/plugins/expression_image/common/types/index.ts
Original file line number Diff line number Diff line change
@@ -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 changes: 13 additions & 0 deletions src/plugins/expression_image/jest.config.js
Original file line number Diff line number Diff line change
@@ -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_image'],
};
9 changes: 9 additions & 0 deletions src/plugins/expression_image/kibana.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"id": "expressionImage",
"version": "1.0.0",
"kibanaVersion": "kibana",
"server": true,
"ui": true,
"requiredPlugins": ["expressions", "presentationUtil"],
"optionalPlugins": []
}
Loading

0 comments on commit 64f00ea

Please sign in to comment.