"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.useRangeSlider = exports.RangeSliderEmbeddable = exports.RangeSliderControlContext = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _react = _interopRequireWildcard(require("react")); var _reactDom = _interopRequireDefault(require("react-dom")); var _lodash = require("lodash"); var _reactRedux = require("react-redux"); var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); var _rxjs = require("rxjs"); var _operators = require("rxjs/operators"); var _esQuery = require("@kbn/es-query"); var _i18n = require("@kbn/i18n"); var _public = require("@kbn/embeddable-plugin/public"); var _public2 = require("@kbn/kibana-react-plugin/public"); var _ = require("../.."); var _services = require("../../services"); var _range_slider_control = require("../components/range_slider_control"); var _range_slider_reducers = require("../range_slider_reducers"); 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 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. */ const diffDataFetchProps = (current, last) => { if (!current || !last) return false; const { filters: currentFilters, ...currentWithoutFilters } = current; const { filters: lastFilters, ...lastWithoutFilters } = last; if (!(0, _fastDeepEqual.default)(currentWithoutFilters, lastWithoutFilters)) return false; if (!(0, _esQuery.compareFilters)(lastFilters !== null && lastFilters !== void 0 ? lastFilters : [], currentFilters !== null && currentFilters !== void 0 ? currentFilters : [], _esQuery.COMPARE_ALL_OPTIONS)) return false; return true; }; const RangeSliderControlContext = /*#__PURE__*/(0, _react.createContext)(null); exports.RangeSliderControlContext = RangeSliderControlContext; const useRangeSlider = () => { const rangeSlider = (0, _react.useContext)(RangeSliderControlContext); if (rangeSlider == null) { throw new Error('useRangeSlider must be used inside RangeSliderControlContext.'); } return rangeSlider; }; exports.useRangeSlider = useRangeSlider; class RangeSliderEmbeddable extends _public.Embeddable { // Controls services // Internal data fetching state for this input control. // state management constructor(reduxToolsPackage, input, output, parent) { super(input, output, parent); // get filters for initial output... // Destructure controls services (0, _defineProperty2.default)(this, "type", _.RANGE_SLIDER_CONTROL); (0, _defineProperty2.default)(this, "deferEmbeddableLoad", true); (0, _defineProperty2.default)(this, "subscriptions", new _rxjs.Subscription()); (0, _defineProperty2.default)(this, "node", void 0); (0, _defineProperty2.default)(this, "dataService", void 0); (0, _defineProperty2.default)(this, "dataViewsService", void 0); (0, _defineProperty2.default)(this, "dataView", void 0); (0, _defineProperty2.default)(this, "field", void 0); (0, _defineProperty2.default)(this, "filters", []); (0, _defineProperty2.default)(this, "select", void 0); (0, _defineProperty2.default)(this, "getState", void 0); (0, _defineProperty2.default)(this, "dispatch", void 0); (0, _defineProperty2.default)(this, "onStateChange", void 0); (0, _defineProperty2.default)(this, "cleanupStateTools", void 0); (0, _defineProperty2.default)(this, "initialize", async () => { const initialValue = this.getInput().value; if (!initialValue) { this.setInitializationFinished(); } try { await this.runRangeSliderQuery(); await this.buildFilter(); } catch (e) { this.onLoadingError(e.message); } if (initialValue) { this.setInitializationFinished(); } this.setupSubscriptions(); }); (0, _defineProperty2.default)(this, "setupSubscriptions", () => { const dataFetchPipe = this.getInput$().pipe((0, _operators.map)(newInput => { var _newInput$ignoreParen; return { validate: !Boolean((_newInput$ignoreParen = newInput.ignoreParentSettings) === null || _newInput$ignoreParen === void 0 ? void 0 : _newInput$ignoreParen.ignoreValidations), lastReloadRequestTime: newInput.lastReloadRequestTime, dataViewId: newInput.dataViewId, fieldName: newInput.fieldName, timeRange: newInput.timeRange, timeslice: newInput.timeslice, filters: newInput.filters, query: newInput.query }; }), (0, _operators.distinctUntilChanged)(diffDataFetchProps), (0, _operators.skip)(1)); // fetch available min/max when input changes this.subscriptions.add(dataFetchPipe.subscribe(async changes => { try { await this.runRangeSliderQuery(); await this.buildFilter(); } catch (e) { this.onLoadingError(e.message); } })); // build filters when value changes this.subscriptions.add(this.getInput$().pipe((0, _operators.distinctUntilChanged)((a, b) => { var _a$value, _b$value; return (0, _lodash.isEqual)((_a$value = a.value) !== null && _a$value !== void 0 ? _a$value : ['', ''], (_b$value = b.value) !== null && _b$value !== void 0 ? _b$value : ['', '']); }), (0, _operators.skip)(1) // skip the first input update because initial filters will be built by initialize. ).subscribe(this.buildFilter)); }); (0, _defineProperty2.default)(this, "getCurrentDataViewAndField", async () => { const { explicitInput: { dataViewId, fieldName } } = this.getState(); if (!this.dataView || this.dataView.id !== dataViewId) { try { this.dataView = await this.dataViewsService.get(dataViewId); this.dispatch.setDataViewId(this.dataView.id); } catch (e) { this.onLoadingError(e.message); } } if (this.dataView && (!this.field || this.field.name !== fieldName)) { this.field = this.dataView.getFieldByName(fieldName); if (this.field) { var _this$field; this.dispatch.setField((_this$field = this.field) === null || _this$field === void 0 ? void 0 : _this$field.toSpec()); } else { this.onLoadingError(_i18n.i18n.translate('controls.rangeSlider.errors.fieldNotFound', { defaultMessage: 'Could not locate field: {fieldName}', values: { fieldName } })); } } return { dataView: this.dataView, field: this.field }; }); (0, _defineProperty2.default)(this, "runRangeSliderQuery", async () => { this.dispatch.setLoading(true); const { dataView, field } = await this.getCurrentDataViewAndField(); if (!dataView || !field) return; const embeddableInput = this.getInput(); const { ignoreParentSettings, timeRange: globalTimeRange, timeslice } = embeddableInput; let { filters = [] } = embeddableInput; const timeRange = timeslice !== undefined ? { from: new Date(timeslice[0]).toISOString(), to: new Date(timeslice[1]).toISOString(), mode: 'absolute' } : globalTimeRange; if (!(ignoreParentSettings !== null && ignoreParentSettings !== void 0 && ignoreParentSettings.ignoreTimerange) && timeRange) { const timeFilter = this.dataService.timefilter.createFilter(dataView, timeRange); if (timeFilter) { filters = filters.concat(timeFilter); } } this.filters = filters; const { min, max } = await this.fetchMinMax({ dataView, field }); this.dispatch.setMinMax({ min: `${min !== null && min !== void 0 ? min : '-Infinity'}`, max: `${max !== null && max !== void 0 ? max : 'Infinity'}` }); }); (0, _defineProperty2.default)(this, "fetchMinMax", async ({ dataView, field }) => { const searchSource = await this.dataService.searchSource.create(); searchSource.setField('size', 0); searchSource.setField('index', dataView); const { ignoreParentSettings, query } = this.getInput(); if (!(ignoreParentSettings !== null && ignoreParentSettings !== void 0 && ignoreParentSettings.ignoreFilters)) { searchSource.setField('filter', this.filters); } if (query) { searchSource.setField('query', query); } const aggBody = {}; if (field) { if (field.scripted) { aggBody.script = { source: field.script, lang: field.lang }; } else { aggBody.field = field.name; } } const aggs = { maxAgg: { max: aggBody }, minAgg: { min: aggBody } }; searchSource.setField('aggs', aggs); const resp = await (0, _rxjs.lastValueFrom)(searchSource.fetch$()); const min = (0, _lodash.get)(resp, 'rawResponse.aggregations.minAgg.value'); const max = (0, _lodash.get)(resp, 'rawResponse.aggregations.maxAgg.value'); return { min, max }; }); (0, _defineProperty2.default)(this, "buildFilter", async () => { const { componentState: { min: availableMin, max: availableMax }, explicitInput: { value } } = this.getState(); const { ignoreParentSettings, query } = this.getInput(); const [selectedMin, selectedMax] = value !== null && value !== void 0 ? value : ['', '']; const hasData = availableMin !== undefined && availableMax !== undefined; const hasLowerSelection = !(0, _lodash.isEmpty)(selectedMin); const hasUpperSelection = !(0, _lodash.isEmpty)(selectedMax); const hasEitherSelection = hasLowerSelection || hasUpperSelection; const { dataView, field } = await this.getCurrentDataViewAndField(); if (!dataView || !field) return; if (!hasData || !hasEitherSelection) { (0, _reactRedux.batch)(() => { this.dispatch.setLoading(false); this.dispatch.setIsInvalid(!(ignoreParentSettings !== null && ignoreParentSettings !== void 0 && ignoreParentSettings.ignoreValidations) && hasEitherSelection); this.dispatch.setDataViewId(dataView.id); this.dispatch.publishFilters([]); this.dispatch.setErrorMessage(undefined); }); return; } const params = {}; if (selectedMin) { params.gte = Math.max(parseFloat(selectedMin), availableMin); } if (selectedMax) { params.lte = Math.min(parseFloat(selectedMax), availableMax); } const rangeFilter = (0, _esQuery.buildRangeFilter)(field, params, dataView); rangeFilter.meta.key = field === null || field === void 0 ? void 0 : field.name; rangeFilter.meta.type = 'range'; rangeFilter.meta.params = params; // Check if new range filter results in no data if (!(ignoreParentSettings !== null && ignoreParentSettings !== void 0 && ignoreParentSettings.ignoreValidations)) { var _resp$rawResponse, _resp$rawResponse$hit; const searchSource = await this.dataService.searchSource.create(); const filters = [...this.filters, rangeFilter]; searchSource.setField('size', 0); searchSource.setField('index', dataView); searchSource.setField('filter', filters); if (query) { searchSource.setField('query', query); } const resp = await (0, _rxjs.lastValueFrom)(searchSource.fetch$()); const total = resp === null || resp === void 0 ? void 0 : (_resp$rawResponse = resp.rawResponse) === null || _resp$rawResponse === void 0 ? void 0 : (_resp$rawResponse$hit = _resp$rawResponse.hits) === null || _resp$rawResponse$hit === void 0 ? void 0 : _resp$rawResponse$hit.total; const docCount = typeof total === 'number' ? total : total === null || total === void 0 ? void 0 : total.value; if (!docCount) { (0, _reactRedux.batch)(() => { this.dispatch.setLoading(false); this.dispatch.setIsInvalid(true); this.dispatch.setDataViewId(dataView.id); this.dispatch.publishFilters([]); this.dispatch.setErrorMessage(undefined); }); return; } } (0, _reactRedux.batch)(() => { this.dispatch.setLoading(false); this.dispatch.setIsInvalid(false); this.dispatch.setDataViewId(dataView.id); this.dispatch.publishFilters([rangeFilter]); this.dispatch.setErrorMessage(undefined); }); }); (0, _defineProperty2.default)(this, "reload", async () => { try { await this.runRangeSliderQuery(); await this.buildFilter(); } catch (e) { this.onLoadingError(e.message); } }); (0, _defineProperty2.default)(this, "destroy", () => { super.destroy(); this.cleanupStateTools(); this.subscriptions.unsubscribe(); }); (0, _defineProperty2.default)(this, "render", node => { if (this.node) { _reactDom.default.unmountComponentAtNode(this.node); } this.node = node; const ControlsServicesProvider = _services.pluginServices.getContextProvider(); _reactDom.default.render( /*#__PURE__*/_react.default.createElement(_public2.KibanaThemeProvider, { theme$: _services.pluginServices.getServices().theme.theme$ }, /*#__PURE__*/_react.default.createElement(ControlsServicesProvider, null, /*#__PURE__*/_react.default.createElement(RangeSliderControlContext.Provider, { value: this }, /*#__PURE__*/_react.default.createElement(_range_slider_control.RangeSliderControl, null)))), node); }); ({ data: this.dataService, dataViews: this.dataViewsService } = _services.pluginServices.getServices()); const reduxEmbeddableTools = reduxToolsPackage.createReduxEmbeddableTools({ embeddable: this, reducers: _range_slider_reducers.rangeSliderReducers, initialComponentState: (0, _range_slider_reducers.getDefaultComponentState)() }); this.select = reduxEmbeddableTools.select; this.getState = reduxEmbeddableTools.getState; this.dispatch = reduxEmbeddableTools.dispatch; this.onStateChange = reduxEmbeddableTools.onStateChange; this.cleanupStateTools = reduxEmbeddableTools.cleanup; this.initialize(); } onLoadingError(errorMessage) { (0, _reactRedux.batch)(() => { this.dispatch.setLoading(false); this.dispatch.publishFilters([]); this.dispatch.setErrorMessage(errorMessage); }); } clearSelections() { this.dispatch.setSelectedRange(['', '']); } isChained() { return true; } } exports.RangeSliderEmbeddable = RangeSliderEmbeddable;