2020-05-05 21:59:32 +02:00
|
|
|
/*
|
|
|
|
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
2021-02-04 03:12:39 +01:00
|
|
|
* 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.
|
2020-05-05 21:59:32 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
import { partition } from 'lodash';
|
|
|
|
import { i18n } from '@kbn/i18n';
|
|
|
|
import { SuggestionRequest, VisualizationSuggestion } from '../types';
|
|
|
|
import { PieVisualizationState } from './types';
|
|
|
|
import { CHART_NAMES, MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS } from './constants';
|
|
|
|
|
|
|
|
function shouldReject({ table, keptLayerIds }: SuggestionRequest<PieVisualizationState>) {
|
|
|
|
return (
|
|
|
|
keptLayerIds.length > 1 ||
|
|
|
|
(keptLayerIds.length && table.layerId !== keptLayerIds[0]) ||
|
|
|
|
table.changeType === 'reorder' ||
|
2020-08-27 00:27:40 +02:00
|
|
|
table.columns.some((col) => col.operation.scale === 'interval') // Histograms are not good for pie
|
2020-05-05 21:59:32 +02:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function suggestions({
|
|
|
|
table,
|
|
|
|
state,
|
|
|
|
keptLayerIds,
|
2020-11-04 11:27:52 +01:00
|
|
|
mainPalette,
|
2020-11-24 09:56:56 +01:00
|
|
|
subVisualizationId,
|
2020-05-05 21:59:32 +02:00
|
|
|
}: SuggestionRequest<PieVisualizationState>): Array<
|
|
|
|
VisualizationSuggestion<PieVisualizationState>
|
|
|
|
> {
|
|
|
|
if (shouldReject({ table, state, keptLayerIds })) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
2020-05-22 09:08:58 +02:00
|
|
|
const [groups, metrics] = partition(table.columns, (col) => col.operation.isBucketed);
|
2020-05-05 21:59:32 +02:00
|
|
|
|
2020-11-24 09:56:56 +01:00
|
|
|
if (metrics.length > 1 || groups.length > Math.max(MAX_PIE_BUCKETS, MAX_TREEMAP_BUCKETS)) {
|
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const incompleteConfiguration = metrics.length === 0 || groups.length === 0;
|
|
|
|
const metricColumnId = metrics.length > 0 ? metrics[0].columnId : undefined;
|
|
|
|
|
|
|
|
if (incompleteConfiguration && state && !subVisualizationId) {
|
|
|
|
// reject incomplete configurations if the sub visualization isn't specifically requested
|
|
|
|
// this allows to switch chart types via switcher with incomplete configurations, but won't
|
|
|
|
// cause incomplete suggestions getting auto applied on dropped fields
|
2020-05-05 21:59:32 +02:00
|
|
|
return [];
|
|
|
|
}
|
|
|
|
|
|
|
|
const results: Array<VisualizationSuggestion<PieVisualizationState>> = [];
|
|
|
|
|
|
|
|
if (groups.length <= MAX_PIE_BUCKETS) {
|
|
|
|
let newShape: PieVisualizationState['shape'] = 'donut';
|
|
|
|
if (groups.length !== 1) {
|
|
|
|
newShape = 'pie';
|
|
|
|
}
|
|
|
|
|
|
|
|
const baseSuggestion: VisualizationSuggestion<PieVisualizationState> = {
|
|
|
|
title: i18n.translate('xpack.lens.pie.suggestionLabel', {
|
|
|
|
defaultMessage: 'As {chartName}',
|
|
|
|
values: { chartName: CHART_NAMES[newShape].label },
|
|
|
|
description: 'chartName is already translated',
|
|
|
|
}),
|
|
|
|
score: state && state.shape !== 'treemap' ? 0.6 : 0.4,
|
|
|
|
state: {
|
|
|
|
shape: newShape,
|
2020-11-04 11:27:52 +01:00
|
|
|
palette: mainPalette || state?.palette,
|
2020-05-05 21:59:32 +02:00
|
|
|
layers: [
|
|
|
|
state?.layers[0]
|
|
|
|
? {
|
|
|
|
...state.layers[0],
|
|
|
|
layerId: table.layerId,
|
2020-05-22 09:08:58 +02:00
|
|
|
groups: groups.map((col) => col.columnId),
|
2020-11-24 09:56:56 +01:00
|
|
|
metric: metricColumnId,
|
2020-05-05 21:59:32 +02:00
|
|
|
}
|
|
|
|
: {
|
|
|
|
layerId: table.layerId,
|
2020-05-22 09:08:58 +02:00
|
|
|
groups: groups.map((col) => col.columnId),
|
2020-11-24 09:56:56 +01:00
|
|
|
metric: metricColumnId,
|
2020-05-05 21:59:32 +02:00
|
|
|
numberDisplay: 'percent',
|
|
|
|
categoryDisplay: 'default',
|
|
|
|
legendDisplay: 'default',
|
|
|
|
nestedLegend: false,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
previewIcon: 'bullseye',
|
|
|
|
// dont show suggestions for same type
|
|
|
|
hide: table.changeType === 'reduced' || (state && state.shape !== 'treemap'),
|
|
|
|
};
|
|
|
|
|
|
|
|
results.push(baseSuggestion);
|
|
|
|
results.push({
|
|
|
|
...baseSuggestion,
|
|
|
|
title: i18n.translate('xpack.lens.pie.suggestionLabel', {
|
|
|
|
defaultMessage: 'As {chartName}',
|
|
|
|
values: { chartName: CHART_NAMES[newShape === 'pie' ? 'donut' : 'pie'].label },
|
|
|
|
description: 'chartName is already translated',
|
|
|
|
}),
|
|
|
|
score: 0.1,
|
|
|
|
state: {
|
|
|
|
...baseSuggestion.state,
|
|
|
|
shape: newShape === 'pie' ? 'donut' : 'pie',
|
|
|
|
},
|
|
|
|
hide: true,
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if (groups.length <= MAX_TREEMAP_BUCKETS) {
|
|
|
|
results.push({
|
|
|
|
title: i18n.translate('xpack.lens.pie.treemapSuggestionLabel', {
|
|
|
|
defaultMessage: 'As Treemap',
|
|
|
|
}),
|
|
|
|
// Use a higher score when currently active, to prevent chart type switching
|
|
|
|
// on the user unintentionally
|
|
|
|
score: state?.shape === 'treemap' ? 0.7 : 0.5,
|
|
|
|
state: {
|
|
|
|
shape: 'treemap',
|
2020-11-04 11:27:52 +01:00
|
|
|
palette: mainPalette || state?.palette,
|
2020-05-05 21:59:32 +02:00
|
|
|
layers: [
|
|
|
|
state?.layers[0]
|
|
|
|
? {
|
|
|
|
...state.layers[0],
|
|
|
|
layerId: table.layerId,
|
2020-05-22 09:08:58 +02:00
|
|
|
groups: groups.map((col) => col.columnId),
|
2020-11-24 09:56:56 +01:00
|
|
|
metric: metricColumnId,
|
2020-05-06 22:45:32 +02:00
|
|
|
categoryDisplay:
|
|
|
|
state.layers[0].categoryDisplay === 'inside'
|
|
|
|
? 'default'
|
|
|
|
: state.layers[0].categoryDisplay,
|
2020-05-05 21:59:32 +02:00
|
|
|
}
|
|
|
|
: {
|
|
|
|
layerId: table.layerId,
|
2020-05-22 09:08:58 +02:00
|
|
|
groups: groups.map((col) => col.columnId),
|
2020-11-24 09:56:56 +01:00
|
|
|
metric: metricColumnId,
|
2020-05-05 21:59:32 +02:00
|
|
|
numberDisplay: 'percent',
|
|
|
|
categoryDisplay: 'default',
|
|
|
|
legendDisplay: 'default',
|
|
|
|
nestedLegend: false,
|
|
|
|
},
|
|
|
|
],
|
|
|
|
},
|
|
|
|
previewIcon: 'bullseye',
|
|
|
|
// hide treemap suggestions from bottom bar, but keep them for chart switcher
|
|
|
|
hide: table.changeType === 'reduced' || !state || (state && state.shape === 'treemap'),
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2020-11-24 09:56:56 +01:00
|
|
|
return [...results]
|
|
|
|
.sort((a, b) => a.score - b.score)
|
|
|
|
.map((suggestion) => ({
|
|
|
|
...suggestion,
|
|
|
|
hide: incompleteConfiguration || suggestion.hide,
|
|
|
|
}));
|
2020-05-05 21:59:32 +02:00
|
|
|
}
|