"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.isCollapsed = exports.hasNonCollapsedSliceBy = exports.getPieVisualization = exports.getDefaultColorForMultiMetricDimension = void 0; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _react = _interopRequireDefault(require("react")); var _i18n = require("@kbn/i18n"); var _i18nReact = require("@kbn/i18n-react"); var _public = require("@kbn/visualizations-plugin/public"); var _eui = require("@elastic/eui"); var _public2 = require("@kbn/expression-xy-plugin/public"); var _to_expression = require("./to_expression"); var _constants = require("../../../common/constants"); var _suggestions = require("./suggestions"); var _partition_charts_meta = require("./partition_charts_meta"); var _toolbar = require("./toolbar"); var _dimension_editor = require("./dimension_editor"); var _layer_settings = require("./layer_settings"); var _render_helpers = require("./render_helpers"); var _utils = require("../../utils"); /* * 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. */ const metricLabel = _i18n.i18n.translate('xpack.lens.pie.groupMetricLabelSingular', { defaultMessage: 'Metric' }); function newLayerState(layerId) { return { layerId, primaryGroups: [], secondaryGroups: undefined, metrics: [], numberDisplay: _constants.NumberDisplay.PERCENT, categoryDisplay: _constants.CategoryDisplay.DEFAULT, legendDisplay: _constants.LegendDisplay.DEFAULT, nestedLegend: false, layerType: _public2.LayerTypes.DATA }; } function isPartitionVisConfiguration(context) { return context.type === 'lnsPie'; } const bucketedOperations = op => op.isBucketed; const numberMetricOperations = op => !op.isBucketed && op.dataType === 'number' && !op.isStaticValue; const isCollapsed = (columnId, layer) => { var _layer$collapseFns; return Boolean((_layer$collapseFns = layer.collapseFns) === null || _layer$collapseFns === void 0 ? void 0 : _layer$collapseFns[columnId]); }; exports.isCollapsed = isCollapsed; const hasNonCollapsedSliceBy = l => { var _ref; const sliceByLength = l.primaryGroups.length; const collapsedGroupsLength = (_ref = l.collapseFns && Object.values(l.collapseFns).filter(Boolean).length) !== null && _ref !== void 0 ? _ref : 0; return sliceByLength - collapsedGroupsLength > 0; }; exports.hasNonCollapsedSliceBy = hasNonCollapsedSliceBy; const getDefaultColorForMultiMetricDimension = ({ layer, columnId, paletteService, datasource, palette }) => { const columnToLabelMap = datasource ? (0, _to_expression.getColumnToLabelMap)(layer.metrics, datasource) : {}; const sortedMetrics = (0, _to_expression.getSortedAccessorsForGroup)(datasource, layer, 'metrics'); return paletteService.get((palette === null || palette === void 0 ? void 0 : palette.name) || 'default').getCategoricalColor([{ name: columnToLabelMap[columnId], rankAtDepth: sortedMetrics.indexOf(columnId), totalSeriesAtDepth: sortedMetrics.length }]); }; exports.getDefaultColorForMultiMetricDimension = getDefaultColorForMultiMetricDimension; const getPieVisualization = ({ paletteService, kibanaTheme }) => ({ id: 'lnsPie', visualizationTypes: Object.entries(_partition_charts_meta.PartitionChartsMeta).map(([key, meta]) => ({ id: key, icon: meta.icon, label: meta.label, groupLabel: meta.groupLabel, showExperimentalBadge: meta.isExperimental })), getVisualizationTypeId(state) { return state.shape; }, getLayerIds(state) { return state.layers.map(l => l.layerId); }, clearLayer(state) { return { shape: state.shape, layers: state.layers.map(l => newLayerState(l.layerId)) }; }, getDescription(state) { var _PartitionChartsMeta$; return (_PartitionChartsMeta$ = _partition_charts_meta.PartitionChartsMeta[state.shape]) !== null && _PartitionChartsMeta$ !== void 0 ? _PartitionChartsMeta$ : _partition_charts_meta.PartitionChartsMeta.pie; }, switchVisualizationType: (visualizationTypeId, state) => ({ ...state, shape: visualizationTypeId }), triggers: [_public.VIS_EVENT_TO_TRIGGER.filter], initialize(addNewLayer, state, mainPalette) { return state || { shape: _constants.PieChartTypes.DONUT, layers: [newLayerState(addNewLayer())], palette: mainPalette }; }, getMainPalette: state => state ? state.palette : undefined, getSuggestions: _suggestions.suggestions, getConfiguration({ state, frame, layerId }) { const layer = state.layers.find(l => l.layerId === layerId); if (!layer) { return { groups: [] }; } const datasource = frame.datasourceLayers[layer.layerId]; const getPrimaryGroupConfig = () => { const originalOrder = (0, _to_expression.getSortedAccessorsForGroup)(datasource, layer, 'primaryGroups'); // When we add a column it could be empty, and therefore have no order const accessors = originalOrder.map(accessor => ({ columnId: accessor, triggerIconType: isCollapsed(accessor, layer) ? 'aggregate' : undefined })); const firstNonCollapsedColumnId = layer.primaryGroups.find(id => !isCollapsed(id, layer)); accessors.forEach(accessorConfig => { if (firstNonCollapsedColumnId === accessorConfig.columnId) { var _state$palette, _state$palette2; accessorConfig.triggerIconType = 'colorBy'; accessorConfig.palette = paletteService.get(((_state$palette = state.palette) === null || _state$palette === void 0 ? void 0 : _state$palette.name) || 'default').getCategoricalColors(10, (_state$palette2 = state.palette) === null || _state$palette2 === void 0 ? void 0 : _state$palette2.params); } }); const primaryGroupConfigBaseProps = { groupId: 'primaryGroups', accessors, enableDimensionEditor: true, filterOperations: bucketedOperations }; // We count multiple metrics as a bucket dimension. // // However, if this is a mosaic chart, we don't support multiple metrics // so if there is more than one metric we got here via a chart switch from // a subtype that supports multi-metrics e.g. pie. // // The user will be prompted to remove the extra metric dimensions and we don't // count multiple metrics as a bucket dimension so that the rest of the dimension // groups UI behaves correctly. const multiMetricsBucketDimensionCount = layer.metrics.length > 1 && state.shape !== _constants.PieChartTypes.MOSAIC ? 1 : 0; const totalNonCollapsedAccessors = accessors.reduce((total, { columnId }) => total + (isCollapsed(columnId, layer) ? 0 : 1), 0) + multiMetricsBucketDimensionCount; const fakeFinalAccessor = layer.metrics.length > 1 && layer.allowMultipleMetrics ? { label: _i18n.i18n.translate('xpack.lens.pie.multiMetricAccessorLabel', { defaultMessage: '{number} metrics', values: { number: layer.metrics.length } }) } : undefined; switch (state.shape) { case _constants.PieChartTypes.DONUT: case _constants.PieChartTypes.PIE: return { ...primaryGroupConfigBaseProps, groupLabel: _i18n.i18n.translate('xpack.lens.pie.sliceGroupLabel', { defaultMessage: 'Slice by' }), dimensionEditorGroupLabel: _i18n.i18n.translate('xpack.lens.pie.sliceDimensionGroupLabel', { defaultMessage: 'Slice' }), fakeFinalAccessor, supportsMoreColumns: totalNonCollapsedAccessors < _partition_charts_meta.PartitionChartsMeta.pie.maxBuckets, dimensionsTooMany: totalNonCollapsedAccessors - _partition_charts_meta.PartitionChartsMeta.pie.maxBuckets, dataTestSubj: 'lnsPie_sliceByDimensionPanel', hideGrouping: true }; case _constants.PieChartTypes.MOSAIC: return { ...primaryGroupConfigBaseProps, groupLabel: _i18n.i18n.translate('xpack.lens.pie.verticalAxisLabel', { defaultMessage: 'Vertical axis' }), dimensionEditorGroupLabel: _i18n.i18n.translate('xpack.lens.pie.verticalAxisDimensionLabel', { defaultMessage: 'Vertical axis' }), supportsMoreColumns: totalNonCollapsedAccessors === 0, dimensionsTooMany: totalNonCollapsedAccessors - 1, dataTestSubj: 'lnsPie_verticalAxisDimensionPanel' }; default: return { ...primaryGroupConfigBaseProps, groupLabel: _i18n.i18n.translate('xpack.lens.pie.treemapGroupLabel', { defaultMessage: 'Group by' }), dimensionEditorGroupLabel: _i18n.i18n.translate('xpack.lens.pie.treemapDimensionGroupLabel', { defaultMessage: 'Group' }), fakeFinalAccessor, supportsMoreColumns: totalNonCollapsedAccessors < _partition_charts_meta.PartitionChartsMeta[state.shape].maxBuckets, dimensionsTooMany: totalNonCollapsedAccessors - _partition_charts_meta.PartitionChartsMeta[state.shape].maxBuckets, dataTestSubj: 'lnsPie_groupByDimensionPanel', hideGrouping: state.shape === _constants.PieChartTypes.TREEMAP }; } }; const getSecondaryGroupConfig = () => { const originalSecondaryOrder = (0, _to_expression.getSortedAccessorsForGroup)(datasource, layer, 'secondaryGroups'); const accessors = originalSecondaryOrder.map(accessor => ({ columnId: accessor, triggerIconType: isCollapsed(accessor, layer) ? 'aggregate' : undefined })); const secondaryGroupConfigBaseProps = { required: true, groupId: 'secondaryGroups', accessors, enableDimensionEditor: true, filterOperations: bucketedOperations }; const totalNonCollapsedAccessors = accessors.reduce((total, { columnId }) => total + (isCollapsed(columnId, layer) ? 0 : 1), 0); switch (state.shape) { case _constants.PieChartTypes.MOSAIC: return { ...secondaryGroupConfigBaseProps, groupLabel: _i18n.i18n.translate('xpack.lens.pie.horizontalAxisLabel', { defaultMessage: 'Horizontal axis' }), dimensionEditorGroupLabel: _i18n.i18n.translate('xpack.lens.pie.horizontalAxisDimensionLabel', { defaultMessage: 'Horizontal axis' }), supportsMoreColumns: totalNonCollapsedAccessors === 0, dimensionsTooMany: totalNonCollapsedAccessors - 1, dataTestSubj: 'lnsPie_horizontalAxisDimensionPanel' }; default: return undefined; } }; const getMetricGroupConfig = () => { const accessors = (0, _to_expression.getSortedAccessorsForGroup)(datasource, layer, 'metrics').map(columnId => { var _ref2, _layer$colorsByDimens, _layer$colorsByDimens2; return { columnId, ...(layer.allowMultipleMetrics ? hasNonCollapsedSliceBy(layer) ? { triggerIconType: 'disabled' } : { triggerIconType: 'color', color: (_ref2 = (_layer$colorsByDimens = (_layer$colorsByDimens2 = layer.colorsByDimension) === null || _layer$colorsByDimens2 === void 0 ? void 0 : _layer$colorsByDimens2[columnId]) !== null && _layer$colorsByDimens !== void 0 ? _layer$colorsByDimens : getDefaultColorForMultiMetricDimension({ layer, columnId, paletteService, datasource, palette: state.palette })) !== null && _ref2 !== void 0 ? _ref2 : undefined } : {}) }; }); const groupLabel = layer.allowMultipleMetrics ? _i18n.i18n.translate('xpack.lens.pie.groupMetricLabel', { defaultMessage: 'Metrics' }) : metricLabel; return { groupId: 'metric', groupLabel, dimensionEditorGroupLabel: groupLabel, paramEditorCustomProps: { headingLabel: _i18n.i18n.translate('xpack.lens.pie.headingLabel', { defaultMessage: 'Value' }) }, accessors, supportsMoreColumns: layer.metrics.length === 0 || Boolean(layer.allowMultipleMetrics), filterOperations: numberMetricOperations, isMetricDimension: true, requiredMinDimensionCount: 1, dimensionsTooMany: layer.allowMultipleMetrics ? 0 : layer.metrics.length - 1, dataTestSubj: 'lnsPie_sizeByDimensionPanel', enableDimensionEditor: true }; }; return { groups: [getPrimaryGroupConfig(), getSecondaryGroupConfig(), getMetricGroupConfig()].filter(_utils.nonNullable) }; }, setDimension({ prevState, layerId, columnId, groupId, previousColumn }) { return { ...prevState, layers: prevState.layers.map(l => { if (l.layerId !== layerId) { return l; } if (groupId === 'primaryGroups') { return { ...l, primaryGroups: [...l.primaryGroups.filter(group => group !== columnId), columnId] }; } if (groupId === 'secondaryGroups') { var _l$secondaryGroups; return { ...l, secondaryGroups: [...(((_l$secondaryGroups = l.secondaryGroups) === null || _l$secondaryGroups === void 0 ? void 0 : _l$secondaryGroups.filter(group => group !== columnId)) || []), columnId] }; } const metrics = [...l.metrics.filter(metric => metric !== columnId), columnId]; return { ...l, metrics }; }) }; }, removeDimension({ prevState, layerId, columnId }) { var _layerToChange$collap, _layerToChange$colors, _newLayer$secondaryGr, _newLayer$secondaryGr2; const newState = { ...prevState }; const layerToChange = prevState.layers.find(l => l.layerId === layerId); if (!layerToChange) { return prevState; } if (layerToChange.primaryGroups.includes(columnId) && layerToChange.primaryGroups.length === 1 && layerToChange.allowMultipleMetrics && layerToChange.metrics.length) { // we don't support palette selection for multiple metrics without a slice-by dimension // so revert to default if the last slice-by is removed delete newState.palette; } let newLayer = { ...layerToChange }; if ((_layerToChange$collap = layerToChange.collapseFns) !== null && _layerToChange$collap !== void 0 && _layerToChange$collap[columnId]) { newLayer.collapseFns = { ...layerToChange.collapseFns }; delete newLayer.collapseFns[columnId]; } if ((_layerToChange$colors = layerToChange.colorsByDimension) !== null && _layerToChange$colors !== void 0 && _layerToChange$colors[columnId]) { newLayer.colorsByDimension = { ...layerToChange.colorsByDimension }; delete newLayer.colorsByDimension[columnId]; } newLayer = { ...newLayer, primaryGroups: newLayer.primaryGroups.filter(c => c !== columnId), secondaryGroups: (_newLayer$secondaryGr = (_newLayer$secondaryGr2 = newLayer.secondaryGroups) === null || _newLayer$secondaryGr2 === void 0 ? void 0 : _newLayer$secondaryGr2.filter(c => c !== columnId)) !== null && _newLayer$secondaryGr !== void 0 ? _newLayer$secondaryGr : undefined, metrics: newLayer.metrics.filter(c => c !== columnId) }; return { ...newState, layers: newState.layers.map(l => l.layerId === layerId ? newLayer : l) }; }, DimensionEditorComponent(props) { return /*#__PURE__*/_react.default.createElement(_dimension_editor.DimensionEditor, (0, _extends2.default)({}, props, { paletteService: paletteService })); }, DimensionEditorDataExtraComponent(props) { return /*#__PURE__*/_react.default.createElement(_dimension_editor.DimensionDataExtraEditor, (0, _extends2.default)({}, props, { paletteService: paletteService })); }, getSupportedLayers() { return [{ type: _public2.LayerTypes.DATA, label: _i18n.i18n.translate('xpack.lens.pie.addLayer', { defaultMessage: 'Visualization' }) }]; }, getLayerType(layerId, state) { var _state$layers$find; return state === null || state === void 0 ? void 0 : (_state$layers$find = state.layers.find(({ layerId: id }) => id === layerId)) === null || _state$layers$find === void 0 ? void 0 : _state$layers$find.layerType; }, toExpression: (state, layers, attributes, datasourceExpressionsByLayers) => (0, _to_expression.toExpression)(state, layers, paletteService, attributes, datasourceExpressionsByLayers), toPreviewExpression: (state, layers, datasourceExpressionsByLayers) => (0, _to_expression.toPreviewExpression)(state, layers, paletteService, datasourceExpressionsByLayers), ToolbarComponent(props) { return /*#__PURE__*/_react.default.createElement(_toolbar.PieToolbar, props); }, hasLayerSettings(props) { return { data: props.state.shape !== _constants.PieChartTypes.MOSAIC, appearance: false }; }, LayerSettingsComponent(props) { return /*#__PURE__*/_react.default.createElement(_layer_settings.LayerSettings, props); }, getSuggestionFromConvertToLensContext(props) { const context = props.context; if (!isPartitionVisConfiguration(context)) { return; } if (!props.suggestions.length) { return; } const suggestionByShape = props.suggestions.find(suggestion => suggestion.visualizationState.shape === context.configuration.shape); if (!suggestionByShape) { return; } const suggestion = { ...suggestionByShape, visualizationState: { ...suggestionByShape.visualizationState, ...context.configuration } }; return suggestion; }, getUserMessages(state, { frame }) { const hasTooManyBucketDimensions = state.layers.map(layer => { var _layer$secondaryGroup; const totalBucketDimensions = Array.from(new Set([...layer.primaryGroups, ...((_layer$secondaryGroup = layer.secondaryGroups) !== null && _layer$secondaryGroup !== void 0 ? _layer$secondaryGroup : [])])).filter(columnId => !isCollapsed(columnId, layer)).length + ( // multiple metrics counts as a dimension layer.metrics.length > 1 ? 1 : 0); return totalBucketDimensions > _partition_charts_meta.PartitionChartsMeta[state.shape].maxBuckets; }).some(Boolean); const errors = hasTooManyBucketDimensions ? [{ severity: 'error', fixableInEditor: true, displayLocations: [{ id: 'visualization' }], shortMessage: _i18n.i18n.translate('xpack.lens.pie.tooManyDimensions', { defaultMessage: 'Your visualization has too many dimensions.' }), longMessage: /*#__PURE__*/_react.default.createElement("span", null, _i18n.i18n.translate('xpack.lens.pie.tooManyDimensionsLong', { defaultMessage: 'Your visualization has too many dimensions. Please follow the instructions in the layer panel.' }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "s" }), _i18n.i18n.translate('xpack.lens.pie.collapsedDimensionsDontCount', { defaultMessage: "(Collapsed dimensions don't count toward this limit.)" })) }] : []; const warningMessages = []; if ((state === null || state === void 0 ? void 0 : state.layers.length) > 0 && frame.activeData) { for (const layer of state.layers) { var _frame$activeData$lay, _frame$activeData$lay2; const { layerId, metrics } = layer; const rows = (_frame$activeData$lay = frame.activeData[layerId]) === null || _frame$activeData$lay === void 0 ? void 0 : _frame$activeData$lay.rows; const numericColumn = (_frame$activeData$lay2 = frame.activeData[layerId]) === null || _frame$activeData$lay2 === void 0 ? void 0 : _frame$activeData$lay2.columns.find(({ meta }) => (meta === null || meta === void 0 ? void 0 : meta.type) === 'number'); if (!rows || !metrics.length) { break; } if (numericColumn && state.shape === _constants.PieChartTypes.WAFFLE && layer.primaryGroups.length && (0, _render_helpers.checkTableForContainsSmallValues)(frame.activeData[layerId], numericColumn.id, 1)) { warningMessages.push({ severity: 'warning', fixableInEditor: true, displayLocations: [{ id: 'toolbar' }], shortMessage: '', longMessage: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { id: "xpack.lens.pie.smallValuesWarningMessage", defaultMessage: "Waffle charts are unable to effectively display small field values. To display all field values, use the Data table or Treemap." }) }); } const metricsWithArrayValues = metrics.map(metricColId => { if (rows.some(row => Array.isArray(row[metricColId]))) { return metricColId; } }).filter(_utils.nonNullable); if (metricsWithArrayValues.length) { const labels = metricsWithArrayValues.map(colId => { var _frame$datasourceLaye, _frame$datasourceLaye2; return ((_frame$datasourceLaye = frame.datasourceLayers[layerId]) === null || _frame$datasourceLaye === void 0 ? void 0 : (_frame$datasourceLaye2 = _frame$datasourceLaye.getOperationForColumnId(colId)) === null || _frame$datasourceLaye2 === void 0 ? void 0 : _frame$datasourceLaye2.label) || colId; }); warningMessages.push({ severity: 'warning', fixableInEditor: true, displayLocations: [{ id: 'toolbar' }], shortMessage: '', longMessage: /*#__PURE__*/_react.default.createElement(_i18nReact.FormattedMessage, { key: labels.join(','), id: "xpack.lens.pie.arrayValues", defaultMessage: "The following dimensions contain array values: {label}. Your visualization may not render as expected.", values: { label: /*#__PURE__*/_react.default.createElement("strong", null, labels.join(', ')) } }) }); } } } return [...errors, ...warningMessages]; }, getVisualizationInfo(state, frame) { var _layer$secondaryGroup2, _layer$secondaryGroup3, _layer$primaryGroups; const layer = state.layers[0]; const dimensions = []; const datasource = frame === null || frame === void 0 ? void 0 : frame.datasourceLayers[layer.layerId]; const hasSliceBy = layer.primaryGroups.length + (((_layer$secondaryGroup2 = layer.secondaryGroups) === null || _layer$secondaryGroup2 === void 0 ? void 0 : _layer$secondaryGroup2.length) || 0); const hasMultipleMetrics = layer.allowMultipleMetrics; const palette = []; if (!hasSliceBy && datasource) { if (hasMultipleMetrics) { palette.push(...layer.metrics.map(columnId => { var _layer$colorsByDimens3, _layer$colorsByDimens4; return (_layer$colorsByDimens3 = (_layer$colorsByDimens4 = layer.colorsByDimension) === null || _layer$colorsByDimens4 === void 0 ? void 0 : _layer$colorsByDimens4[columnId]) !== null && _layer$colorsByDimens3 !== void 0 ? _layer$colorsByDimens3 : getDefaultColorForMultiMetricDimension({ layer, columnId, paletteService, datasource, palette: state.palette }); })); } else if (!hasNonCollapsedSliceBy(layer)) { var _state$palette3; // This is a logic integrated in the renderer, here simulated // In the particular case of no color assigned (as no sliceBy dimension defined) // the color is generated on the fly from the default palette palette.push(...paletteService.get(((_state$palette3 = state.palette) === null || _state$palette3 === void 0 ? void 0 : _state$palette3.name) || 'default').getCategoricalColors(Math.max(10, layer.metrics.length)).slice(0, layer.metrics.length)); } } layer.metrics.forEach(metric => { dimensions.push({ id: metric, name: metricLabel, dimensionType: 'metric' }); }); if (state.shape === _constants.PieChartTypes.MOSAIC && (_layer$secondaryGroup3 = layer.secondaryGroups) !== null && _layer$secondaryGroup3 !== void 0 && _layer$secondaryGroup3.length) { layer.secondaryGroups.forEach(accessor => { dimensions.push({ name: _i18n.i18n.translate('xpack.lens.pie.horizontalAxisLabel', { defaultMessage: 'Horizontal axis' }), dimensionType: 'horizontal_axis', id: accessor }); }); } if ((_layer$primaryGroups = layer.primaryGroups) !== null && _layer$primaryGroups !== void 0 && _layer$primaryGroups.length) { let name = _i18n.i18n.translate('xpack.lens.pie.treemapGroupLabel', { defaultMessage: 'Group by' }); let dimensionType = 'group_by'; if (state.shape === _constants.PieChartTypes.MOSAIC) { name = _i18n.i18n.translate('xpack.lens.pie.verticalAxisLabel', { defaultMessage: 'Vertical axis' }); dimensionType = 'vertical_axis'; } if (state.shape === _constants.PieChartTypes.DONUT || state.shape === _constants.PieChartTypes.PIE) { name = _i18n.i18n.translate('xpack.lens.pie.sliceGroupLabel', { defaultMessage: 'Slice by' }); dimensionType = 'slice_by'; } layer.primaryGroups.forEach(accessor => { dimensions.push({ name, dimensionType, id: accessor }); }); if (hasNonCollapsedSliceBy(layer)) { var _state$palette4, _state$palette5; palette.push(...paletteService.get(((_state$palette4 = state.palette) === null || _state$palette4 === void 0 ? void 0 : _state$palette4.name) || 'default').getCategoricalColors(10, (_state$palette5 = state.palette) === null || _state$palette5 === void 0 ? void 0 : _state$palette5.params)); } } const finalPalette = palette.filter(_utils.nonNullable); return { layers: [{ layerId: layer.layerId, layerType: layer.layerType, chartType: state.shape, ...this.getDescription(state), dimensions, palette: finalPalette.length ? finalPalette : undefined }] }; } }); exports.getPieVisualization = getPieVisualization;