"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.DimensionEditor = DimensionEditor; exports.DimensionEditorAdditionalSection = DimensionEditorAdditionalSection; var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")); var _eui = require("@elastic/eui"); var _react = _interopRequireWildcard(require("react")); var _i18n = require("@kbn/i18n"); var _coloring = require("@kbn/coloring"); var _public = require("@kbn/expression-metric-vis-plugin/public"); var _utils = require("@kbn/visualizations-plugin/common/utils"); var _react2 = require("@emotion/react"); var _visualizationUiComponents = require("@kbn/visualization-ui-components"); var _utils2 = require("../../../common/expressions/datatable/utils"); var _shared_components = require("../../shared_components"); var _palette_config = require("./palette_config"); var _visualization = require("./visualization"); var _collapse_setting = require("../../shared_components/collapse_setting"); var _icon_set = require("./icon_set"); function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); } function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; } /* * 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. */ function DimensionEditor(props) { const { state, accessor } = props; const idPrefix = (0, _eui.htmlIdGenerator)()(); switch (accessor) { case state === null || state === void 0 ? void 0 : state.metricAccessor: return /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": "lnsMetricDimensionEditor_primary_metric" }, /*#__PURE__*/_react.default.createElement(PrimaryMetricEditor, (0, _extends2.default)({}, props, { idPrefix: idPrefix }))); case state.secondaryMetricAccessor: return /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": "lnsMetricDimensionEditor_secondary_metric" }, /*#__PURE__*/_react.default.createElement(SecondaryMetricEditor, (0, _extends2.default)({}, props, { idPrefix: idPrefix }))); case state.maxAccessor: return /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": "lnsMetricDimensionEditor_maximum" }, /*#__PURE__*/_react.default.createElement(MaximumEditor, (0, _extends2.default)({}, props, { idPrefix: idPrefix }))); case state.breakdownByAccessor: return /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": "lnsMetricDimensionEditor_breakdown" }, /*#__PURE__*/_react.default.createElement(BreakdownByEditor, (0, _extends2.default)({}, props, { idPrefix: idPrefix }))); default: return null; } } function BreakdownByEditor({ setState, state }) { var _state$maxCols; const setMaxCols = (0, _react.useCallback)(columns => { setState({ ...state, maxCols: parseInt(columns, 10) }); }, [setState, state]); const { inputValue: currentMaxCols, handleInputChange: handleMaxColsChange } = (0, _visualizationUiComponents.useDebouncedValue)({ onChange: setMaxCols, value: String((_state$maxCols = state.maxCols) !== null && _state$maxCols !== void 0 ? _state$maxCols : _visualization.DEFAULT_MAX_COLUMNS) }); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { label: _i18n.i18n.translate('xpack.lens.metric.maxColumns', { defaultMessage: 'Layout columns' }), fullWidth: true, display: "columnCompressed" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFieldNumber, { compressed: true, min: 1, "data-test-subj": "lnsMetric_max_cols", value: currentMaxCols, onChange: ({ target: { value } }) => handleMaxColsChange(value) })), /*#__PURE__*/_react.default.createElement(_collapse_setting.CollapseSetting, { value: state.collapseFn || '', onChange: collapseFn => { setState({ ...state, collapseFn }); } })); } function MaximumEditor({ setState, state, idPrefix }) { return null; } function SecondaryMetricEditor({ accessor, idPrefix, frame, layerId, setState, state }) { var _getColumnByAccessor, _frame$activeData; const columnName = (_getColumnByAccessor = (0, _utils.getColumnByAccessor)(accessor, (_frame$activeData = frame.activeData) === null || _frame$activeData === void 0 ? void 0 : _frame$activeData[layerId].columns)) === null || _getColumnByAccessor === void 0 ? void 0 : _getColumnByAccessor.name; const defaultPrefix = columnName || ''; return /*#__PURE__*/_react.default.createElement("div", { "data-test-subj": "lnsMetricDimensionEditor_secondary_metric" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: _i18n.i18n.translate('xpack.lens.metric.prefixText.label', { defaultMessage: 'Prefix' }) }, /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonGroup, { isFullWidth: true, buttonSize: "compressed", legend: _i18n.i18n.translate('xpack.lens.metric.prefix.label', { defaultMessage: 'Prefix' }), "data-test-subj": "lnsMetric_prefix_buttons", options: [{ id: `${idPrefix}auto`, label: _i18n.i18n.translate('xpack.lens.metric.prefix.auto', { defaultMessage: 'Auto' }), 'data-test-subj': 'lnsMetric_prefix_auto', value: undefined }, { id: `${idPrefix}custom`, label: _i18n.i18n.translate('xpack.lens.metric.prefix.custom', { defaultMessage: 'Custom' }), 'data-test-subj': 'lnsMetric_prefix_custom', value: defaultPrefix }, { id: `${idPrefix}none`, label: _i18n.i18n.translate('xpack.lens.metric.prefix.none', { defaultMessage: 'None' }), 'data-test-subj': 'lnsMetric_prefix_none', value: '' }], idSelected: `${idPrefix}${state.secondaryPrefix === undefined ? 'auto' : state.secondaryPrefix === '' ? 'none' : 'custom'}`, onChange: (_id, secondaryPrefix) => { setState({ ...state, secondaryPrefix }); } }), /*#__PURE__*/_react.default.createElement(_eui.EuiSpacer, { size: "s" }), state.secondaryPrefix && /*#__PURE__*/_react.default.createElement(_visualizationUiComponents.DebouncedInput, { compressed: true, value: state.secondaryPrefix, onChange: newPrefix => { setState({ ...state, secondaryPrefix: newPrefix }); } })))); } function PrimaryMetricEditor(props) { var _frame$activeData2, _state$palette, _state$palette$params, _frame$activeData3, _currentMinMax$min, _currentMinMax$max; const { state, setState, frame, accessor, idPrefix } = props; const [isPaletteOpen, setIsPaletteOpen] = (0, _react.useState)(false); const currentData = (_frame$activeData2 = frame.activeData) === null || _frame$activeData2 === void 0 ? void 0 : _frame$activeData2[state.layerId]; if (accessor == null || !(0, _utils2.isNumericFieldForDatatable)(currentData, accessor)) { return null; } const hasDynamicColoring = Boolean(state === null || state === void 0 ? void 0 : state.palette); const supportsPercentPalette = Boolean(state.maxAccessor || state.breakdownByAccessor && !state.collapseFn || (state === null || state === void 0 ? void 0 : (_state$palette = state.palette) === null || _state$palette === void 0 ? void 0 : (_state$palette$params = _state$palette.params) === null || _state$palette$params === void 0 ? void 0 : _state$palette$params.rangeType) === 'percent'); const activePalette = (state === null || state === void 0 ? void 0 : state.palette) || { type: 'palette', name: (supportsPercentPalette ? _palette_config.defaultPercentagePaletteParams : _palette_config.defaultNumberPaletteParams).name, params: { ...(supportsPercentPalette ? _palette_config.defaultPercentagePaletteParams : _palette_config.defaultNumberPaletteParams) } }; const currentMinMax = (0, _public.getDataBoundsForPalette)({ metric: state.metricAccessor, max: state.maxAccessor, // if we're collapsing, pretend like there's no breakdown to match the activeData breakdownBy: !state.collapseFn ? state.breakdownByAccessor : undefined }, (_frame$activeData3 = frame.activeData) === null || _frame$activeData3 === void 0 ? void 0 : _frame$activeData3[state.layerId]); const displayStops = (0, _shared_components.applyPaletteParams)(props.paletteService, activePalette, { min: (_currentMinMax$min = currentMinMax.min) !== null && _currentMinMax$min !== void 0 ? _currentMinMax$min : _coloring.DEFAULT_MIN_STOP, max: (_currentMinMax$max = currentMinMax.max) !== null && _currentMinMax$max !== void 0 ? _currentMinMax$max : _coloring.DEFAULT_MAX_STOP }); const togglePalette = () => setIsPaletteOpen(!isPaletteOpen); return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: _i18n.i18n.translate('xpack.lens.metric.dynamicColoring.label', { defaultMessage: 'Color mode' }) }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonGroup, { isFullWidth: true, buttonSize: "compressed", legend: _i18n.i18n.translate('xpack.lens.metric.colorMode.label', { defaultMessage: 'Color mode' }), "data-test-subj": "lnsMetric_color_mode_buttons", options: [{ id: `${idPrefix}static`, label: _i18n.i18n.translate('xpack.lens.metric.colorMode.static', { defaultMessage: 'Static' }), 'data-test-subj': 'lnsMetric_color_mode_static' }, { id: `${idPrefix}dynamic`, label: _i18n.i18n.translate('xpack.lens.metric.colorMode.dynamic', { defaultMessage: 'Dynamic' }), 'data-test-subj': 'lnsMetric_color_mode_dynamic' }], idSelected: `${idPrefix}${state.palette ? 'dynamic' : 'static'}`, onChange: id => { const colorMode = id.replace(idPrefix, ''); const params = colorMode === 'dynamic' ? { palette: { ...activePalette, params: { ...activePalette.params, stops: displayStops } } } : { palette: undefined }; setState({ ...state, color: undefined, ...params }); } })), !hasDynamicColoring && /*#__PURE__*/_react.default.createElement(StaticColorControls, props), hasDynamicColoring && /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: _i18n.i18n.translate('xpack.lens.paletteMetricGradient.label', { defaultMessage: 'Color' }) }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexGroup, { alignItems: "center", gutterSize: "s", responsive: false, className: "lnsDynamicColoringClickable" }, /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, null, /*#__PURE__*/_react.default.createElement(_eui.EuiColorPaletteDisplay, { "data-test-subj": "lnsMetric_dynamicColoring_palette", palette: displayStops.map(({ color }) => color), type: _coloring.FIXED_PROGRESSION, onClick: togglePalette })), /*#__PURE__*/_react.default.createElement(_eui.EuiFlexItem, { grow: false }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonEmpty, { "data-test-subj": "lnsMetric_dynamicColoring_trigger", iconType: "controlsHorizontal", onClick: togglePalette, size: "xs", flush: "both" }, _i18n.i18n.translate('xpack.lens.paletteTableGradient.customize', { defaultMessage: 'Edit' })), /*#__PURE__*/_react.default.createElement(_shared_components.PalettePanelContainer, { siblingRef: props.panelRef, isOpen: isPaletteOpen, handleClose: togglePalette }, /*#__PURE__*/_react.default.createElement(_coloring.CustomizablePalette, { palettes: props.paletteService, activePalette: activePalette, dataBounds: currentMinMax, showRangeTypeSelector: supportsPercentPalette, setPalette: newPalette => { setState({ ...state, palette: newPalette }); } }))))), /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: _i18n.i18n.translate('xpack.lens.metric.icon', { defaultMessage: 'Icon decoration' }) }, /*#__PURE__*/_react.default.createElement(_visualizationUiComponents.IconSelect, { customIconSet: _icon_set.iconsSet, value: state === null || state === void 0 ? void 0 : state.icon, onChange: newIcon => { setState({ ...state, icon: newIcon }); } }))); } function StaticColorControls({ state, setState }) { const colorLabel = _i18n.i18n.translate('xpack.lens.metric.color', { defaultMessage: 'Color' }); const setColor = (0, _react.useCallback)(color => { setState({ ...state, color: color === '' ? undefined : color }); }, [setState, state]); const { inputValue: currentColor, handleInputChange: handleColorChange } = (0, _visualizationUiComponents.useDebouncedValue)({ onChange: setColor, value: state.color || (0, _visualization.getDefaultColor)(state) }, { allowFalsyValue: true }); return /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: colorLabel }, /*#__PURE__*/_react.default.createElement(_eui.EuiColorPicker, { fullWidth: true, compressed: true, isClearable: false, onChange: color => handleColorChange(color), color: currentColor, "aria-label": colorLabel, showAlpha: false, swatches: (0, _eui.euiPaletteColorBlind)() })); } function DimensionEditorAdditionalSection({ state, datasource, setState, addLayer, removeLayer, accessor }) { var _datasource$getOperat, _datasource$getOperat2, _state$progressDirect; const { euiTheme } = (0, _eui.useEuiTheme)(); if (accessor !== state.metricAccessor) { return null; } const idPrefix = (0, _eui.htmlIdGenerator)()(); const hasDefaultTimeField = datasource === null || datasource === void 0 ? void 0 : datasource.hasDefaultTimeField(); const metricHasReducedTimeRange = Boolean(state.metricAccessor && (datasource === null || datasource === void 0 ? void 0 : (_datasource$getOperat = datasource.getOperationForColumnId(state.metricAccessor)) === null || _datasource$getOperat === void 0 ? void 0 : _datasource$getOperat.hasReducedTimeRange)); const secondaryMetricHasReducedTimeRange = Boolean(state.secondaryMetricAccessor && (datasource === null || datasource === void 0 ? void 0 : (_datasource$getOperat2 = datasource.getOperationForColumnId(state.secondaryMetricAccessor)) === null || _datasource$getOperat2 === void 0 ? void 0 : _datasource$getOperat2.hasReducedTimeRange)); const supportingVisHelpTexts = []; const supportsTrendline = hasDefaultTimeField && !metricHasReducedTimeRange && !secondaryMetricHasReducedTimeRange; if (!supportsTrendline) { supportingVisHelpTexts.push(!hasDefaultTimeField ? _i18n.i18n.translate('xpack.lens.metric.supportingVis.needDefaultTimeField', { defaultMessage: 'Line visualizations require use of a data view with a default time field.' }) : metricHasReducedTimeRange ? _i18n.i18n.translate('xpack.lens.metric.supportingVis.metricHasReducedTimeRange', { defaultMessage: 'Line visualizations cannot be used when a reduced time range is applied to the primary metric.' }) : secondaryMetricHasReducedTimeRange ? _i18n.i18n.translate('xpack.lens.metric.supportingVis.secondaryMetricHasReducedTimeRange', { defaultMessage: 'Line visualizations cannot be used when a reduced time range is applied to the secondary metric.' }) : ''); } if (!state.maxAccessor) { supportingVisHelpTexts.push(_i18n.i18n.translate('xpack.lens.metric.summportingVis.needMaxDimension', { defaultMessage: 'Bar visualizations require a maximum value to be defined.' })); } const buttonIdPrefix = `${idPrefix}--`; return /*#__PURE__*/_react.default.createElement("div", { className: "lnsIndexPatternDimensionEditor--padded lnsIndexPatternDimensionEditor--collapseNext" }, /*#__PURE__*/_react.default.createElement(_eui.EuiText, { size: "s", css: (0, _react2.css)` margin-bottom: ${euiTheme.size.base}; ` }, /*#__PURE__*/_react.default.createElement("h4", null, _i18n.i18n.translate('xpack.lens.metric.supportingVis.label', { defaultMessage: 'Supporting visualization' }))), /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { display: "columnCompressed", fullWidth: true, label: _i18n.i18n.translate('xpack.lens.metric.supportingVis.type', { defaultMessage: 'Type' }), helpText: supportingVisHelpTexts.map(text => /*#__PURE__*/_react.default.createElement("p", null, text)) }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonGroup, { isFullWidth: true, buttonSize: "compressed", legend: _i18n.i18n.translate('xpack.lens.metric.supportingVis.type', { defaultMessage: 'Type' }), "data-test-subj": "lnsMetric_supporting_visualization_buttons", options: [{ id: `${buttonIdPrefix}none`, label: _i18n.i18n.translate('xpack.lens.metric.supportingVisualization.none', { defaultMessage: 'None' }), 'data-test-subj': 'lnsMetric_supporting_visualization_none' }, { id: `${buttonIdPrefix}trendline`, label: _i18n.i18n.translate('xpack.lens.metric.supportingVisualization.trendline', { defaultMessage: 'Line' }), isDisabled: !supportsTrendline, 'data-test-subj': 'lnsMetric_supporting_visualization_trendline' }, { id: `${buttonIdPrefix}bar`, label: _i18n.i18n.translate('xpack.lens.metric.supportingVisualization.bar', { defaultMessage: 'Bar' }), isDisabled: !state.maxAccessor, 'data-test-subj': 'lnsMetric_supporting_visualization_bar' }], idSelected: `${buttonIdPrefix}${state.trendlineLayerId ? 'trendline' : (0, _visualization.showingBar)(state) ? 'bar' : 'none'}`, onChange: id => { const supportingVisualizationType = id.split('--')[1]; switch (supportingVisualizationType) { case 'trendline': setState({ ...state, showBar: false }); addLayer('metricTrendline'); break; case 'bar': setState({ ...state, showBar: true }); if (state.trendlineLayerId) removeLayer(state.trendlineLayerId); break; case 'none': setState({ ...state, showBar: false }); if (state.trendlineLayerId) removeLayer(state.trendlineLayerId); break; } } })), (0, _visualization.showingBar)(state) && /*#__PURE__*/_react.default.createElement(_eui.EuiFormRow, { label: _i18n.i18n.translate('xpack.lens.metric.progressDirectionLabel', { defaultMessage: 'Bar orientation' }), fullWidth: true, display: "columnCompressed" }, /*#__PURE__*/_react.default.createElement(_eui.EuiButtonGroup, { isFullWidth: true, buttonSize: "compressed", legend: _i18n.i18n.translate('xpack.lens.metric.progressDirectionLabel', { defaultMessage: 'Bar orientation' }), "data-test-subj": "lnsMetric_progress_direction_buttons", name: "alignment", options: [{ id: `${idPrefix}vertical`, label: _i18n.i18n.translate('xpack.lens.metric.progressDirection.vertical', { defaultMessage: 'Vertical' }), 'data-test-subj': 'lnsMetric_progress_bar_vertical' }, { id: `${idPrefix}horizontal`, label: _i18n.i18n.translate('xpack.lens.metric.progressDirection.horizontal', { defaultMessage: 'Horizontal' }), 'data-test-subj': 'lnsMetric_progress_bar_horizontal' }], idSelected: `${idPrefix}${(_state$progressDirect = state.progressDirection) !== null && _state$progressDirect !== void 0 ? _state$progressDirect : 'vertical'}`, onChange: id => { const newDirection = id.replace(idPrefix, ''); setState({ ...state, progressDirection: newDirection }); } })))); }