[lens] tag cloud (#157751)

Part of https://github.com/elastic/kibana/issues/154307
Closes https://github.com/elastic/kibana/issues/95542

PR adds tagcloud visualization to lens

<img width="600" alt="Screen Shot 2023-05-31 at 1 11 00 PM"
src="f54f76a3-9757-4a00-ac65-a203e5bb113a">

---------

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Stratoula Kalafateli <efstratia.kalafateli@elastic.co>
This commit is contained in:
Nathan Reese 2023-06-08 08:09:20 -06:00 committed by GitHub
parent 6e81ae83bc
commit ec62e15529
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 736 additions and 33 deletions

View file

@ -40,4 +40,5 @@ export {
IconChartHeatmap,
IconChartHorizontalBullet,
IconChartVerticalBullet,
IconChartTagcloud,
} from './src/assets';

View file

@ -0,0 +1,29 @@
/*
* 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, { FunctionComponent } from 'react';
import type { EuiIconProps } from '@elastic/eui';
import { colors } from './common_styles';
export const IconChartTagcloud: FunctionComponent = ({
title,
titleId,
...props
}: Omit<EuiIconProps, 'type'>) => (
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="22" viewBox="0 0 30 22" {...props}>
{title ? <title id={titleId} /> : null}
<path
d="M19 5a2 2 0 0 1 2-2h4a2 2 0 1 1 0 4h-4a2 2 0 0 1-2-2ZM2 11a2 2 0 0 1 2-2h8a2 2 0 1 1 0 4H4a2 2 0 0 1-2-2Zm15 4a2 2 0 1 0 0 4h6a2 2 0 1 0 0-4h-6Z"
className={colors.accent}
/>
<path
d="M6 4a1 1 0 0 0 0 2h4a1 1 0 1 0 0-2H6Zm8 0a1 1 0 1 0 0 2h2a1 1 0 1 0 0-2h-2Zm2 7a1 1 0 0 1 1-1h10a1 1 0 1 1 0 2H17a1 1 0 0 1-1-1Zm-8 5a1 1 0 1 0 0 2h4a1 1 0 1 0 0-2H8Z"
className={colors.subdued}
/>
</svg>
);

View file

@ -40,3 +40,4 @@ export { IconRegionMap } from './region_map';
export { IconChartHeatmap } from './chart_heatmap';
export { IconChartHorizontalBullet } from './chart_horizontal_bullet';
export { IconChartVerticalBullet } from './chart_vertical_bullet';
export { IconChartTagcloud } from './chart_tagcloud';

View file

@ -66,6 +66,7 @@ Object {
"bucket": Object {
"accessor": 1,
},
"isPreview": false,
"maxFontSize": 72,
"metric": Object {
"accessor": 0,
@ -125,6 +126,7 @@ Object {
},
"type": "vis_dimension",
},
"isPreview": false,
"maxFontSize": 72,
"metric": Object {
"accessor": Object {

View file

@ -20,7 +20,7 @@ const strings = {
help: i18n.translate('expressionTagcloud.functions.tagcloudHelpText', {
defaultMessage: 'Tagcloud visualization.',
}),
args: {
argHelp: {
scale: i18n.translate('expressionTagcloud.functions.tagcloud.args.scaleHelpText', {
defaultMessage: 'Scale to determine font size of a word',
}),
@ -48,6 +48,9 @@ const strings = {
ariaLabel: i18n.translate('expressionTagcloud.functions.tagcloud.args.ariaLabelHelpText', {
defaultMessage: 'Specifies the aria label of the tagcloud',
}),
isPreview: i18n.translate('expressionTagcloud.functions.tagcloud.args.isPreviewHelpText', {
defaultMessage: 'Set isPreview to true to avoid showing out of room warnings',
}),
},
dimension: {
tags: i18n.translate('expressionTagcloud.functions.tagcloud.dimension.tags', {
@ -81,7 +84,7 @@ export const errors = {
};
export const tagcloudFunction: ExpressionTagcloudFunction = () => {
const { help, args: argHelp, dimension } = strings;
const { help, argHelp, dimension } = strings;
return {
name: EXPRESSION_NAME,
@ -137,6 +140,12 @@ export const tagcloudFunction: ExpressionTagcloudFunction = () => {
help: argHelp.ariaLabel,
required: false,
},
isPreview: {
types: ['boolean'],
help: argHelp.isPreview,
default: false,
required: false,
},
},
fn(input, args, handlers) {
validateAccessor(args.metric, input.columns);
@ -157,6 +166,7 @@ export const tagcloudFunction: ExpressionTagcloudFunction = () => {
args.ariaLabel ??
(handlers.variables?.embeddableTitle as string) ??
handlers.getExecutionContext?.()?.description,
isPreview: Boolean(args.isPreview),
};
if (handlers?.inspectorAdapters?.tables) {

View file

@ -7,3 +7,5 @@
*/
export { EXPRESSION_NAME, ScaleOptions, Orientation } from './constants';
export type { ExpressionTagcloudFunctionDefinition } from './types/expression_functions';

View file

@ -17,23 +17,23 @@ import { ExpressionValueVisDimension } from '@kbn/visualizations-plugin/common';
import { EXPRESSION_NAME, ScaleOptions, Orientation } from '../constants';
interface TagCloudCommonParams {
scale: $Values<typeof ScaleOptions>;
scale?: $Values<typeof ScaleOptions>;
orientation: $Values<typeof Orientation>;
minFontSize: number;
maxFontSize: number;
showLabel: boolean;
ariaLabel?: string;
metric: ExpressionValueVisDimension | string;
bucket?: ExpressionValueVisDimension | string;
palette: PaletteOutput;
}
export interface TagCloudVisConfig extends TagCloudCommonParams {
metric: ExpressionValueVisDimension | string;
bucket?: ExpressionValueVisDimension | string;
isPreview?: boolean;
}
export interface TagCloudRendererParams extends TagCloudCommonParams {
palette: PaletteOutput;
metric: ExpressionValueVisDimension | string;
bucket?: ExpressionValueVisDimension | string;
isPreview: boolean;
}
export interface TagcloudRendererConfig {
@ -43,13 +43,11 @@ export interface TagcloudRendererConfig {
syncColors: boolean;
}
interface Arguments extends TagCloudVisConfig {
palette: PaletteOutput;
}
export type ExpressionTagcloudFunction = () => ExpressionFunctionDefinition<
'tagcloud',
export type ExpressionTagcloudFunctionDefinition = ExpressionFunctionDefinition<
typeof EXPRESSION_NAME,
Datatable,
Arguments,
TagCloudVisConfig,
ExpressionValueRender<TagcloudRendererConfig>
>;
export type ExpressionTagcloudFunction = () => ExpressionTagcloudFunctionDefinition;

View file

@ -20,6 +20,9 @@
"requiredBundles": [
"kibanaUtils",
"kibanaReact"
],
"extraPublicDirs": [
"common"
]
}
}

View file

@ -57,6 +57,7 @@ const config: TagcloudRendererConfig = {
format: { id: 'string', params: {} },
},
palette: { type: 'palette', name: 'default' },
isPreview: false,
},
syncColors: false,
};

View file

@ -61,6 +61,7 @@ const visParams: TagCloudRendererParams = {
minFontSize: 12,
maxFontSize: 70,
showLabel: true,
isPreview: false,
};
const formattedData: WordcloudSpec['data'] = [

View file

@ -10,14 +10,12 @@ import React, { useCallback, useState, useMemo } from 'react';
import { FormattedMessage } from '@kbn/i18n-react';
import { throttle } from 'lodash';
import { EuiIconTip, EuiResizeObserver } from '@elastic/eui';
import { IconChartTagcloud } from '@kbn/chart-icons';
import { Chart, Settings, Wordcloud, RenderChangeListener } from '@elastic/charts';
import { EmptyPlaceholder } from '@kbn/charts-plugin/public';
import type { PaletteRegistry, PaletteOutput } from '@kbn/coloring';
import { IInterpreterRenderHandlers } from '@kbn/expressions-plugin/public';
import {
getColumnByAccessor,
getAccessor,
getFormatByAccessor,
} from '@kbn/visualizations-plugin/common/utils';
import { getColumnByAccessor, getFormatByAccessor } from '@kbn/visualizations-plugin/common/utils';
import { getFormatService } from '../format_service';
import { TagcloudRendererConfig } from '../../common/types';
import { ScaleOptions, Orientation } from '../../common/constants';
@ -153,6 +151,11 @@ export const TagCloudChart = ({
const termsBucketId = getColumnByAccessor(bucket, visData.columns)!.id;
const clickedValue = elements[0][0].text;
const columnIndex = visData.columns.findIndex((col) => col.id === termsBucketId);
if (columnIndex < 0) {
return;
}
const rowIndex = visData.rows.findIndex((row) => {
const formattedValue = bucketFormatter
? bucketFormatter.convert(row[termsBucketId], 'text')
@ -170,7 +173,7 @@ export const TagCloudChart = ({
data: [
{
table: visData,
column: getAccessor(bucket),
column: columnIndex,
row: rowIndex,
},
],
@ -180,6 +183,10 @@ export const TagCloudChart = ({
[bucket, bucketFormatter, fireEvent, visData]
);
if (visData.rows.length === 0) {
return <EmptyPlaceholder icon={IconChartTagcloud} renderComplete={renderComplete} />;
}
return (
<EuiResizeObserver onResize={updateChart}>
{(resizeRef) => (
@ -215,7 +222,7 @@ export const TagCloudChart = ({
{label}
</div>
)}
{warning && (
{!visParams.isPreview && warning && (
<div className="tgcChart__warning">
<EuiIconTip
type="warning"
@ -229,7 +236,7 @@ export const TagCloudChart = ({
/>
</div>
)}
{tagCloudData.length > MAX_TAG_COUNT && (
{!visParams.isPreview && tagCloudData.length > MAX_TAG_COUNT && (
<div className="tgcChart__warning">
<EuiIconTip
type="warning"

View file

@ -68,8 +68,6 @@ export const tagcloudRenderer: (
const palettesRegistry = await plugins.charts.palettes.getPalettes();
const showNoResult = config.visData.rows.length === 0;
render(
<KibanaThemeProvider theme$={core.theme.theme$}>
<I18nProvider>
@ -81,7 +79,6 @@ export const tagcloudRenderer: (
// It is used for rendering at `Canvas`.
className={cx('tagCloudContainer', css(tagCloudVisClass))}
renderComplete={renderComplete}
showNoResult={showNoResult}
>
<TagCloudChart
{...config}

View file

@ -26,6 +26,7 @@
"@kbn/kibana-react-plugin",
"@kbn/analytics",
"@kbn/chart-expressions-common",
"@kbn/chart-icons",
],
"exclude": [
"target/**/*",

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"isPreview":false,"maxFontSize":72,"metric":{"accessor":1,"format":{"id":"number","params":{}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"isPreview":false,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[],"type":"datatable"},"visParams":{"ariaLabel":null,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[],"type":"datatable"},"visParams":{"ariaLabel":null,"isPreview":false,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"isPreview":false,"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"isPreview":false,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"log","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"isPreview":false,"maxFontSize":72,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":18,"orientation":"multiple","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"log","showLabel":true},"visType":"tagcloud"}}

View file

@ -1 +1 @@
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}
{"as":"tagcloud","type":"render","value":{"syncColors":false,"visData":{"columns":[{"id":"col-0-2","meta":{"field":"response.raw","index":"logstash-*","params":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"2","indexPatternId":"logstash-*","params":{"excludeIsRegex":true,"field":"response.raw","includeIsRegex":true,"missingBucket":false,"missingBucketLabel":"Missing","order":"desc","orderBy":"1","otherBucket":false,"otherBucketLabel":"Other","size":4},"schema":"segment","type":"terms"},"type":"string"},"name":"response.raw: Descending"},{"id":"col-1-1","meta":{"field":null,"index":"logstash-*","params":{"id":"number"},"source":"esaggs","sourceParams":{"appliedTimeRange":null,"enabled":true,"hasPrecisionError":false,"id":"1","indexPatternId":"logstash-*","params":{"emptyAsNull":false},"schema":"metric","type":"count"},"type":"number"},"name":"Count"}],"meta":{"source":"logstash-*","statistics":{"totalCount":14004},"type":"esaggs"},"rows":[{"col-0-2":"200","col-1-1":12891},{"col-0-2":"404","col-1-1":696},{"col-0-2":"503","col-1-1":417}],"type":"datatable"},"visParams":{"ariaLabel":null,"bucket":{"accessor":1,"format":{"id":"number"},"type":"vis_dimension"},"isPreview":false,"maxFontSize":40,"metric":{"accessor":0,"format":{"id":"terms","params":{"id":"string","missingBucketLabel":"Missing","otherBucketLabel":"Other"}},"type":"vis_dimension"},"minFontSize":20,"orientation":"single","palette":{"name":"custom","params":{"colors":["#882E72","#B178A6","#D6C1DE","#1965B0","#5289C7","#7BAFDE","#4EB265","#90C987","#CAE0AB","#F7EE55","#F6C141","#F1932D","#E8601C","#DC050C"],"continuity":"above","gradient":false,"range":"percent","rangeMax":null,"rangeMin":0,"stops":[]},"type":"palette"},"scale":"linear","showLabel":true},"visType":"tagcloud"}}

View file

@ -33,6 +33,7 @@
"expressionMetricVis",
"expressionHeatmap",
"expressionXY",
"expressionTagcloud",
"eventAnnotation",
"unifiedSearch",
"unifiedFieldList",

View file

@ -28,6 +28,8 @@ export * from './visualizations/heatmap/heatmap_visualization';
export * from './visualizations/heatmap';
export * from './visualizations/gauge/gauge_visualization';
export * from './visualizations/gauge';
export * from './visualizations/tagcloud/tagcloud_visualization';
export * from './visualizations/tagcloud';
export * from './datasources/form_based/form_based';
export { getTextBasedDatasource } from './datasources/text_based/text_based_languages';

View file

@ -90,6 +90,7 @@ import type {
} from './visualizations/partition';
import type { HeatmapVisualization as HeatmapVisualizationType } from './visualizations/heatmap';
import type { GaugeVisualization as GaugeVisualizationType } from './visualizations/gauge';
import type { TagcloudVisualization as TagcloudVisualizationType } from './visualizations/tagcloud';
import { APP_ID, getEditPath, NOT_INTERNATIONALIZED_PRODUCT_NAME } from '../common/constants';
import type { FormatFactory } from '../common/types';
@ -270,6 +271,7 @@ export class LensPlugin {
private pieVisualization: PieVisualizationType | undefined;
private heatmapVisualization: HeatmapVisualizationType | undefined;
private gaugeVisualization: GaugeVisualizationType | undefined;
private tagcloudVisualization: TagcloudVisualizationType | undefined;
private topNavMenuEntries: LensTopNavMenuEntryGenerator[] = [];
private hasDiscoverAccess: boolean = false;
private dataViewsService: DataViewsPublicPluginStart | undefined;
@ -501,6 +503,7 @@ export class LensPlugin {
PieVisualization,
HeatmapVisualization,
GaugeVisualization,
TagcloudVisualization,
TextBasedDatasource,
} = await import('./async_services');
this.datatableVisualization = new DatatableVisualization();
@ -513,6 +516,7 @@ export class LensPlugin {
this.pieVisualization = new PieVisualization();
this.heatmapVisualization = new HeatmapVisualization();
this.gaugeVisualization = new GaugeVisualization();
this.tagcloudVisualization = new TagcloudVisualization();
const editorFrameSetupInterface = this.editorFrameService.setup();
@ -537,6 +541,7 @@ export class LensPlugin {
this.pieVisualization.setup(core, dependencies);
this.heatmapVisualization.setup(core, dependencies);
this.gaugeVisualization.setup(core, dependencies);
this.tagcloudVisualization.setup(core, dependencies);
this.queuedVisualizations.forEach((queuedVis) => {
editorFrameSetupInterface.registerVisualization(queuedVis);

View file

@ -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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { i18n } from '@kbn/i18n';
import { $Values } from '@kbn/utility-types';
import { Orientation } from '@kbn/expression-tagcloud-plugin/common';
export const TAGCLOUD_LABEL = i18n.translate('xpack.lens.tagcloud.label', {
defaultMessage: 'Tag cloud',
});
export const DEFAULT_STATE = {
maxFontSize: 72,
minFontSize: 18,
orientation: Orientation.SINGLE as $Values<typeof Orientation>,
showLabel: true,
};

View file

@ -0,0 +1,25 @@
/*
* 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 type { CoreSetup } from '@kbn/core/public';
import type { ChartsPluginSetup } from '@kbn/charts-plugin/public';
import type { EditorFrameSetup } from '../../types';
export interface TagcloudVisualizationPluginSetupPlugins {
editorFrame: EditorFrameSetup;
charts: ChartsPluginSetup;
}
export class TagcloudVisualization {
setup(core: CoreSetup, { editorFrame, charts }: TagcloudVisualizationPluginSetupPlugins) {
editorFrame.registerVisualization(async () => {
const { getTagcloudVisualization } = await import('../../async_services');
const palettes = await charts.palettes.getPalettes();
return getTagcloudVisualization({ paletteService: palettes, theme: core.theme });
});
}
}

View file

@ -0,0 +1,54 @@
/*
* 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 { partition } from 'lodash';
import { IconChartTagcloud } from '@kbn/chart-icons';
import type { SuggestionRequest, VisualizationSuggestion } from '../../types';
import type { TagcloudState } from './types';
import { DEFAULT_STATE, TAGCLOUD_LABEL } from './constants';
export function suggestions({
table,
state,
keptLayerIds,
mainPalette,
subVisualizationId,
}: SuggestionRequest<TagcloudState>): Array<VisualizationSuggestion<TagcloudState>> {
const isUnchanged = state && table.changeType === 'unchanged';
if (
isUnchanged ||
keptLayerIds.length > 1 ||
(keptLayerIds.length && table.layerId !== keptLayerIds[0])
) {
return [];
}
const [buckets, metrics] = partition(table.columns, (col) => col.operation.isBucketed);
if (buckets.length !== 1 || metrics.length !== 1) {
return [];
}
return buckets
.filter((bucket) => {
return bucket.operation.dataType !== 'date';
})
.map((bucket) => {
return {
previewIcon: IconChartTagcloud,
title: TAGCLOUD_LABEL,
hide: true, // hide suggestions while in tech preview
score: 0.1,
state: {
layerId: table.layerId,
tagAccessor: bucket.columnId,
valueAccessor: metrics[0].columnId,
...DEFAULT_STATE,
},
};
});
}

View file

@ -0,0 +1,56 @@
/*
* 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 React, { useEffect, useState } from 'react';
import useDebounce from 'react-use/lib/useDebounce';
import { EuiDualRange } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
interface Props {
minFontSize: number;
maxFontSize: number;
onChange: (minFontSize: number, maxFontSize: number) => void;
}
export function FontSizeInput(props: Props) {
const [fontSize, setFontSize] = useState<[number, number]>([
props.minFontSize,
props.maxFontSize,
]);
const [, cancel] = useDebounce(
() => {
props.onChange(fontSize[0], fontSize[1]);
},
150,
[fontSize]
);
useEffect(() => {
return () => {
cancel();
};
}, [cancel]);
return (
<EuiDualRange
id="tagCloudFontSizeSlider"
min={1}
max={120}
step={1}
value={fontSize}
onChange={(value) => {
setFontSize(value as [number, number]);
}}
showLabels
compressed
aria-label={i18n.translate('xpack.lens.label.tagcloud.fontSizeLabel', {
defaultMessage: 'Font size',
})}
/>
);
}

View file

@ -0,0 +1,8 @@
/*
* 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.
*/
export { TagcloudToolbar } from './tagcloud_toolbar';

View file

@ -0,0 +1,127 @@
/*
* 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.
*/
/*
* 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 React, { ChangeEvent } from 'react';
import {
EuiFlexGroup,
EuiFlexItem,
EuiFormRow,
EuiSelect,
EuiSwitch,
EuiSwitchEvent,
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { $Values } from '@kbn/utility-types';
import { Orientation } from '@kbn/expression-tagcloud-plugin/common';
import type { VisualizationToolbarProps } from '../../../types';
import { ToolbarPopover } from '../../../shared_components';
import type { TagcloudState } from '../types';
import { FontSizeInput } from './font_size_input';
const ORIENTATION_OPTIONS = [
{
value: Orientation.SINGLE,
text: i18n.translate('xpack.lens.label.tagcloud.orientation.single', {
defaultMessage: 'Single',
}),
},
{
value: Orientation.RIGHT_ANGLED,
text: i18n.translate('xpack.lens.label.tagcloud.orientation.rightAngled', {
defaultMessage: 'Right angled',
}),
},
{
value: Orientation.MULTIPLE,
text: i18n.translate('xpack.lens.label.tagcloud.orientation.multiple', {
defaultMessage: 'Multiple',
}),
},
];
export function TagcloudToolbar(props: VisualizationToolbarProps<TagcloudState>) {
return (
<EuiFlexGroup alignItems="center" gutterSize="s" responsive={false}>
<EuiFlexItem grow={false}>
<EuiFlexGroup alignItems="center" gutterSize="none" responsive={false}>
<ToolbarPopover
title={i18n.translate('xpack.lens.tagcloud.appearanceLabel', {
defaultMessage: 'Appearance',
})}
type="visualOptions"
buttonDataTestSubj="lnsVisualOptionsButton"
>
<EuiFormRow
display="columnCompressed"
label={i18n.translate('xpack.lens.label.tagcloud.fontSizeLabel', {
defaultMessage: 'Font size',
})}
>
<FontSizeInput
minFontSize={props.state.minFontSize}
maxFontSize={props.state.maxFontSize}
onChange={(minFontSize: number, maxFontSize: number) => {
props.setState({
...props.state,
minFontSize,
maxFontSize,
});
}}
/>
</EuiFormRow>
<EuiFormRow
display="columnCompressed"
label={i18n.translate('xpack.lens.label.tagcloud.orientationLabel', {
defaultMessage: 'Orientation',
})}
>
<EuiSelect
options={ORIENTATION_OPTIONS}
value={props.state.orientation}
onChange={(event: ChangeEvent<HTMLSelectElement>) => {
props.setState({
...props.state,
orientation: event.target.value as $Values<typeof Orientation>,
});
}}
compressed
/>
</EuiFormRow>
<EuiFormRow
display="columnCompressed"
label={i18n.translate('xpack.lens.label.tagcloud.showLabel', {
defaultMessage: 'Show label',
})}
>
<EuiSwitch
label={i18n.translate('xpack.lens.label.tagcloud.showLabel', {
defaultMessage: 'Show label',
})}
showLabel={false}
checked={props.state.showLabel}
onChange={(event: EuiSwitchEvent) => {
props.setState({
...props.state,
showLabel: event.target.checked,
});
}}
compressed
/>
</EuiFormRow>
</ToolbarPopover>
</EuiFlexGroup>
</EuiFlexItem>
</EuiFlexGroup>
);
}

View file

@ -0,0 +1,286 @@
/*
* 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 React from 'react';
import { i18n } from '@kbn/i18n';
import { I18nProvider } from '@kbn/i18n-react';
import { render } from 'react-dom';
import { ThemeServiceStart } from '@kbn/core/public';
import { KibanaThemeProvider } from '@kbn/kibana-react-plugin/public';
import { VIS_EVENT_TO_TRIGGER } from '@kbn/visualizations-plugin/public';
import type { ExpressionTagcloudFunctionDefinition } from '@kbn/expression-tagcloud-plugin/common';
import { LayerTypes } from '@kbn/expression-xy-plugin/public';
import {
buildExpression,
buildExpressionFunction,
ExpressionFunctionTheme,
} from '@kbn/expressions-plugin/common';
import { PaletteRegistry } from '@kbn/coloring';
import { IconChartTagcloud } from '@kbn/chart-icons';
import { SystemPaletteExpressionFunctionDefinition } from '@kbn/charts-plugin/common';
import type { OperationMetadata, Visualization } from '../..';
import type { TagcloudState } from './types';
import { suggestions } from './suggestions';
import { TagcloudToolbar } from './tagcloud_toolbar';
import { TagsDimensionEditor } from './tags_dimension_editor';
import { DEFAULT_STATE, TAGCLOUD_LABEL } from './constants';
const TAG_GROUP_ID = 'tags';
const METRIC_GROUP_ID = 'metric';
export const getTagcloudVisualization = ({
paletteService,
theme,
}: {
paletteService: PaletteRegistry;
theme: ThemeServiceStart;
}): Visualization<TagcloudState> => ({
id: 'lnsTagcloud',
visualizationTypes: [
{
id: 'lnsTagcloud',
icon: IconChartTagcloud,
label: TAGCLOUD_LABEL,
groupLabel: i18n.translate('xpack.lens.pie.groupLabel', {
defaultMessage: 'Proportion',
}),
showExperimentalBadge: true,
},
],
getVisualizationTypeId() {
return 'lnsTagcloud';
},
clearLayer(state) {
const newState = {
...state,
...DEFAULT_STATE,
};
delete newState.tagAccessor;
delete newState.valueAccessor;
delete newState.palette;
return newState;
},
getLayerIds(state) {
return [state.layerId];
},
getDescription() {
return {
icon: IconChartTagcloud,
label: TAGCLOUD_LABEL,
};
},
getSuggestions: suggestions,
triggers: [VIS_EVENT_TO_TRIGGER.filter],
initialize(addNewLayer, state) {
return (
state || {
layerId: addNewLayer(),
layerType: LayerTypes.DATA,
...DEFAULT_STATE,
}
);
},
getConfiguration({ state }) {
return {
groups: [
{
groupId: TAG_GROUP_ID,
groupLabel: i18n.translate('xpack.lens.tagcloud.tagLabel', {
defaultMessage: 'Tags',
}),
layerId: state.layerId,
accessors: state.tagAccessor
? [
{
columnId: state.tagAccessor,
triggerIconType: 'colorBy',
palette: paletteService
.get(state.palette?.name || 'default')
.getCategoricalColors(10, state.palette?.params),
},
]
: [],
supportsMoreColumns: !state.tagAccessor,
filterOperations: (op: OperationMetadata) => op.isBucketed,
enableDimensionEditor: true,
required: true,
requiredMinDimensionCount: 1,
dataTestSubj: 'lnsTagcloud_tagDimensionPanel',
},
{
groupId: METRIC_GROUP_ID,
groupLabel: i18n.translate('xpack.lens.tagcloud.metricValueLabel', {
defaultMessage: 'Metric',
}),
isMetricDimension: true,
layerId: state.layerId,
accessors: state.valueAccessor ? [{ columnId: state.valueAccessor }] : [],
supportsMoreColumns: !state.valueAccessor,
filterOperations: (op: OperationMetadata) => !op.isBucketed && op.dataType === 'number',
enableDimensionEditor: true,
required: true,
requiredMinDimensionCount: 1,
dataTestSubj: 'lnsTagcloud_valueDimensionPanel',
},
],
};
},
getSupportedLayers() {
return [
{
type: LayerTypes.DATA,
label: i18n.translate('xpack.lens.tagcloud.addLayer', {
defaultMessage: 'Add visualization layer',
}),
},
];
},
getLayerType(layerId, state) {
if (state?.layerId === layerId) {
return LayerTypes.DATA;
}
},
toExpression: (state, datasourceLayers, attributes, datasourceExpressionsByLayers = {}) => {
if (!state.tagAccessor || !state.valueAccessor) {
return null;
}
const datasourceExpression = datasourceExpressionsByLayers[state.layerId];
return {
type: 'expression',
chain: [
...(datasourceExpression ? datasourceExpression.chain : []),
buildExpressionFunction<ExpressionTagcloudFunctionDefinition>('tagcloud', {
bucket: state.tagAccessor,
metric: state.valueAccessor,
maxFontSize: state.maxFontSize,
minFontSize: state.minFontSize,
orientation: state.orientation,
palette: buildExpression([
state.palette
? buildExpressionFunction<ExpressionFunctionTheme>('theme', {
variable: 'palette',
default: [
paletteService.get(state.palette.name).toExpression(state.palette.params),
],
})
: buildExpressionFunction<SystemPaletteExpressionFunctionDefinition>(
'system_palette',
{
name: 'default',
}
),
]).toAst(),
showLabel: state.showLabel,
}).toAst(),
],
};
},
toPreviewExpression: (state, datasourceLayers, datasourceExpressionsByLayers = {}) => {
if (!state.tagAccessor || !state.valueAccessor) {
return null;
}
const datasourceExpression = datasourceExpressionsByLayers[state.layerId];
return {
type: 'expression',
chain: [
...(datasourceExpression ? datasourceExpression.chain : []),
buildExpressionFunction<ExpressionTagcloudFunctionDefinition>('tagcloud', {
bucket: state.tagAccessor,
isPreview: true,
metric: state.valueAccessor,
maxFontSize: 18,
minFontSize: 4,
orientation: state.orientation,
palette: buildExpression([
state.palette
? buildExpressionFunction<ExpressionFunctionTheme>('theme', {
variable: 'palette',
default: [
paletteService.get(state.palette.name).toExpression(state.palette.params),
],
})
: buildExpressionFunction<SystemPaletteExpressionFunctionDefinition>(
'system_palette',
{
name: 'default',
}
),
]).toAst(),
showLabel: false,
}).toAst(),
],
};
},
setDimension({ columnId, groupId, prevState }) {
const update: Partial<TagcloudState> = {};
if (groupId === TAG_GROUP_ID) {
update.tagAccessor = columnId;
} else if (groupId === METRIC_GROUP_ID) {
update.valueAccessor = columnId;
}
return {
...prevState,
...update,
};
},
removeDimension({ prevState, layerId, columnId }) {
const update = { ...prevState };
if (prevState.tagAccessor === columnId) {
delete update.tagAccessor;
} else if (prevState.valueAccessor === columnId) {
delete update.valueAccessor;
}
return update;
},
renderDimensionEditor(domElement, props) {
if (props.groupId === TAG_GROUP_ID) {
render(
<KibanaThemeProvider theme$={theme.theme$}>
<I18nProvider>
<TagsDimensionEditor
paletteService={paletteService}
state={props.state}
setState={props.setState}
/>
</I18nProvider>
</KibanaThemeProvider>,
domElement
);
}
},
renderToolbar(domElement, props) {
render(
<KibanaThemeProvider theme$={theme.theme$}>
<I18nProvider>
<TagcloudToolbar {...props} />
</I18nProvider>
</KibanaThemeProvider>,
domElement
);
},
});

View file

@ -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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React from 'react';
import { PaletteRegistry } from '@kbn/coloring';
import type { TagcloudState } from './types';
import { PalettePicker } from '../../shared_components';
interface Props {
paletteService: PaletteRegistry;
state: TagcloudState;
setState: (state: TagcloudState) => void;
}
export function TagsDimensionEditor(props: Props) {
return (
<PalettePicker
palettes={props.paletteService}
activePalette={props.state.palette}
setPalette={(newPalette) => {
props.setState({
...props.state,
palette: newPalette,
});
}}
/>
);
}

View file

@ -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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { $Values } from '@kbn/utility-types';
import { Datatable } from '@kbn/expressions-plugin/common';
import type { PaletteOutput } from '@kbn/coloring';
import { Orientation } from '@kbn/expression-tagcloud-plugin/common';
export interface TagcloudState {
layerId: string;
tagAccessor?: string;
valueAccessor?: string;
maxFontSize: number;
minFontSize: number;
orientation: $Values<typeof Orientation>;
palette?: PaletteOutput;
showLabel: boolean;
}
export interface TagcloudConfig extends TagcloudState {
title: string;
description: string;
}
export interface TagcloudProps {
data: Datatable;
args: TagcloudConfig;
}

View file

@ -34,6 +34,7 @@
"@kbn/expression-gauge-plugin",
"@kbn/expression-legacy-metric-vis-plugin",
"@kbn/expression-metric-vis-plugin",
"@kbn/expression-tagcloud-plugin",
"@kbn/data-view-editor-plugin",
"@kbn/event-annotation-plugin",
"@kbn/expression-xy-plugin",