"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.VisualizeEmbeddable = void 0; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _lodash = _interopRequireWildcard(require("lodash")); var _rxjs = require("rxjs"); var _i18n = require("@kbn/i18n"); var _react = _interopRequireDefault(require("react")); var _reactDom = require("react-dom"); var _eui = require("@elastic/eui"); var _esQuery = require("@kbn/es-query"); var _public = require("@kbn/kibana-react-plugin/public"); var _public2 = require("@kbn/charts-plugin/public"); var _public3 = require("@kbn/embeddable-plugin/public"); var _public4 = require("@kbn/data-views-plugin/public"); var _public5 = require("@kbn/data-plugin/public"); var _utils = require("../visualize_app/utils"); var _visualization_missed_saved_object_error = require("../components/visualization_missed_saved_object_error"); var _visualization_error = _interopRequireDefault(require("../components/visualization_error")); var _constants = require("./constants"); var _services = require("../services"); var _events = require("./events"); var _saved_visualize_utils = require("../utils/saved_visualize_utils"); var _to_ast = require("./to_ast"); 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. */ class VisualizeEmbeddable extends _public3.Embeddable { constructor(timefilter, { vis, editPath, editUrl, indexPatterns, deps, capabilities }, initialInput, attributeService, parent) { super(initialInput, { defaultTitle: vis.title, defaultDescription: vis.description, editPath, editApp: 'visualize', editUrl, indexPatterns, visTypeName: vis.type.name }, parent); (0, _defineProperty2.default)(this, "handler", void 0); (0, _defineProperty2.default)(this, "timefilter", void 0); (0, _defineProperty2.default)(this, "timeRange", void 0); (0, _defineProperty2.default)(this, "query", void 0); (0, _defineProperty2.default)(this, "filters", void 0); (0, _defineProperty2.default)(this, "searchSessionId", void 0); (0, _defineProperty2.default)(this, "syncColors", void 0); (0, _defineProperty2.default)(this, "syncTooltips", void 0); (0, _defineProperty2.default)(this, "syncCursor", void 0); (0, _defineProperty2.default)(this, "embeddableTitle", void 0); (0, _defineProperty2.default)(this, "visCustomizations", void 0); (0, _defineProperty2.default)(this, "subscriptions", []); (0, _defineProperty2.default)(this, "expression", void 0); (0, _defineProperty2.default)(this, "vis", void 0); (0, _defineProperty2.default)(this, "domNode", void 0); (0, _defineProperty2.default)(this, "warningDomNode", void 0); (0, _defineProperty2.default)(this, "type", _constants.VISUALIZE_EMBEDDABLE_TYPE); (0, _defineProperty2.default)(this, "abortController", void 0); (0, _defineProperty2.default)(this, "deps", void 0); (0, _defineProperty2.default)(this, "inspectorAdapters", void 0); (0, _defineProperty2.default)(this, "attributeService", void 0); (0, _defineProperty2.default)(this, "expressionVariables", void 0); (0, _defineProperty2.default)(this, "expressionVariablesSubject", new _rxjs.ReplaySubject(1)); (0, _defineProperty2.default)(this, "getInspectorAdapters", () => { if (!this.handler || this.inspectorAdapters && !Object.keys(this.inspectorAdapters).length) { return undefined; } return this.handler.inspect(); }); (0, _defineProperty2.default)(this, "openInspector", () => { if (!this.handler) return; const adapters = this.handler.inspect(); if (!adapters) return; return this.deps.start().plugins.inspector.open(adapters, { title: this.getTitle() || _i18n.i18n.translate('visualizations.embeddable.inspectorTitle', { defaultMessage: 'Inspector' }) }); }); // this is a hack to make editor still work, will be removed once we clean up editor // @ts-ignore (0, _defineProperty2.default)(this, "hasInspector", () => Boolean(this.getInspectorAdapters())); (0, _defineProperty2.default)(this, "onContainerLoading", () => { this.renderComplete.dispatchInProgress(); this.updateOutput({ ...this.getOutput(), loading: true, rendered: false, error: undefined }); }); (0, _defineProperty2.default)(this, "onContainerData", () => { this.handleWarnings(); this.updateOutput({ ...this.getOutput(), loading: false }); }); (0, _defineProperty2.default)(this, "onContainerRender", () => { this.renderComplete.dispatchComplete(); this.updateOutput({ ...this.getOutput(), rendered: true }); }); (0, _defineProperty2.default)(this, "onContainerError", error => { if (this.abortController) { this.abortController.abort(); } this.renderComplete.dispatchError(); if ((0, _utils.isFallbackDataView)(this.vis.data.indexPattern)) { var _this$vis$data$indexP; error = new Error(_i18n.i18n.translate('visualizations.missedDataView.errorMessage', { defaultMessage: `Could not find the {type}: {id}`, values: { id: (_this$vis$data$indexP = this.vis.data.indexPattern.id) !== null && _this$vis$data$indexP !== void 0 ? _this$vis$data$indexP : '-', type: this.vis.data.savedSearchId ? _i18n.i18n.translate('visualizations.noSearch.label', { defaultMessage: 'search' }) : _i18n.i18n.translate('visualizations.noDataView.label', { defaultMessage: 'data view' }) } })); } this.updateOutput({ ...this.getOutput(), rendered: true, error }); }); (0, _defineProperty2.default)(this, "reload", async () => { await this.handleVisUpdate(); }); (0, _defineProperty2.default)(this, "handleVisUpdate", async () => { this.handleChanges(); await this.updateHandler(); }); (0, _defineProperty2.default)(this, "uiStateChangeHandler", () => { this.updateInput({ ...this.vis.uiState.toJSON() }); }); (0, _defineProperty2.default)(this, "inputIsRefType", input => { if (!this.attributeService) { throw new Error('AttributeService must be defined for getInputAsRefType'); } return this.attributeService.inputIsRefType(input); }); (0, _defineProperty2.default)(this, "getInputAsValueType", async () => { const input = { savedVis: this.vis.serialize() }; delete input.savedVis.id; _lodash.default.unset(input, 'savedVis.title'); return new Promise(resolve => { resolve({ ...input }); }); }); (0, _defineProperty2.default)(this, "getInputAsRefType", async () => { const { data, spaces, savedObjectsTaggingOss } = await this.deps.start().plugins; const savedVis = await (0, _saved_visualize_utils.getSavedVisualization)({ search: data.search, dataViews: data.dataViews, spaces, savedObjectsTagging: savedObjectsTaggingOss === null || savedObjectsTaggingOss === void 0 ? void 0 : savedObjectsTaggingOss.getTaggingApi() }); if (!savedVis) { throw new Error('Error creating a saved vis object'); } if (!this.attributeService) { throw new Error('AttributeService must be defined for getInputAsRefType'); } const saveModalTitle = this.getTitle() ? this.getTitle() : _i18n.i18n.translate('visualizations.embeddable.placeholderTitle', { defaultMessage: 'Placeholder Title' }); // @ts-ignore const attributes = { savedVis, vis: this.vis, title: this.vis.title }; return this.attributeService.getInputAsRefType({ id: this.id, attributes }, { showSaveModal: true, saveModalTitle }); }); this.deps = deps; this.timefilter = timefilter; this.syncColors = this.input.syncColors; this.syncTooltips = this.input.syncTooltips; this.syncCursor = this.input.syncCursor; this.searchSessionId = this.input.searchSessionId; this.query = this.input.query; this.embeddableTitle = this.getTitle(); this.vis = vis; this.vis.uiState.on('change', this.uiStateChangeHandler); this.vis.uiState.on('reload', this.reload); this.attributeService = attributeService; if (this.attributeService) { const readOnly = Boolean(vis.type.disableEdit); const isByValue = !this.inputIsRefType(initialInput); const editable = readOnly ? false : capabilities.visualizeSave || isByValue && capabilities.dashboardSave && capabilities.visualizeOpen; this.updateOutput({ ...this.getOutput(), editable }); } this.subscriptions.push(this.getInput$().subscribe(() => { const isDirty = this.handleChanges(); if (isDirty && this.handler) { this.updateHandler(); } })); const inspectorAdapters = this.vis.type.inspectorAdapters; if (inspectorAdapters) { this.inspectorAdapters = typeof inspectorAdapters === 'function' ? inspectorAdapters() : inspectorAdapters; } } reportsEmbeddableLoad() { return true; } getVis() { return this.vis; } /** * Gets the Visualize embeddable's local filters * @returns Local/panel-level array of filters for Visualize embeddable */ async getFilters() { var _input$savedVis$data$, _input$savedVis, _input$savedVis$data$2; let input = this.getInput(); if (this.inputIsRefType(input)) { input = await this.getInputAsValueType(); } const filters = (_input$savedVis$data$ = (_input$savedVis = input.savedVis) === null || _input$savedVis === void 0 ? void 0 : (_input$savedVis$data$2 = _input$savedVis.data.searchSource) === null || _input$savedVis$data$2 === void 0 ? void 0 : _input$savedVis$data$2.filter) !== null && _input$savedVis$data$ !== void 0 ? _input$savedVis$data$ : []; // must clone the filters so that it's not read only, because mapAndFlattenFilters modifies the array return (0, _public5.mapAndFlattenFilters)(_lodash.default.cloneDeep(filters)); } /** * Gets the Visualize embeddable's local query * @returns Local/panel-level query for Visualize embeddable */ async getQuery() { var _input$savedVis2, _input$savedVis2$data; let input = this.getInput(); if (this.inputIsRefType(input)) { input = await this.getInputAsValueType(); } return (_input$savedVis2 = input.savedVis) === null || _input$savedVis2 === void 0 ? void 0 : (_input$savedVis2$data = _input$savedVis2.data.searchSource) === null || _input$savedVis2$data === void 0 ? void 0 : _input$savedVis2$data.query; } /** * Transfers all changes in the containerState.customization into * the uiState of this visualization. */ transferCustomizationsToUiState() { // Check for changes that need to be forwarded to the uiState // Since the vis has an own listener on the uiState we don't need to // pass anything from here to the handler.update method const visCustomizations = { vis: this.input.vis, table: this.input.table }; if (visCustomizations.vis || visCustomizations.table) { if (!_lodash.default.isEqual(visCustomizations, this.visCustomizations)) { this.visCustomizations = visCustomizations; // Turn this off or the uiStateChangeHandler will fire for every modification. this.vis.uiState.off('change', this.uiStateChangeHandler); this.vis.uiState.clearAllKeys(); Object.entries(visCustomizations).forEach(([key, value]) => { if (value) { this.vis.uiState.set(key, value); } }); this.vis.uiState.on('change', this.uiStateChangeHandler); } } else if (this.parent) { this.vis.uiState.clearAllKeys(); } } handleChanges() { this.transferCustomizationsToUiState(); let dirty = false; // Check if timerange has changed const nextTimeRange = this.input.timeslice !== undefined ? { from: new Date(this.input.timeslice[0]).toISOString(), to: new Date(this.input.timeslice[1]).toISOString(), mode: 'absolute' } : this.input.timeRange; if (!_lodash.default.isEqual(nextTimeRange, this.timeRange)) { this.timeRange = _lodash.default.cloneDeep(nextTimeRange); dirty = true; } // Check if filters has changed if (!(0, _esQuery.onlyDisabledFiltersChanged)(this.input.filters, this.filters)) { this.filters = this.input.filters; dirty = true; } // Check if query has changed if (!_lodash.default.isEqual(this.input.query, this.query)) { this.query = this.input.query; dirty = true; } if (this.searchSessionId !== this.input.searchSessionId) { this.searchSessionId = this.input.searchSessionId; dirty = true; } if (this.syncColors !== this.input.syncColors) { this.syncColors = this.input.syncColors; dirty = true; } if (this.syncTooltips !== this.input.syncTooltips) { this.syncTooltips = this.input.syncTooltips; dirty = true; } if (this.syncCursor !== this.input.syncCursor) { this.syncCursor = this.input.syncCursor; dirty = true; } if (this.embeddableTitle !== this.getTitle()) { this.embeddableTitle = this.getTitle(); dirty = true; } if (this.vis.description && this.domNode) { this.domNode.setAttribute('data-description', this.vis.description); } return dirty; } handleWarnings() { var _this$getInspectorAda; const warnings = []; if ((_this$getInspectorAda = this.getInspectorAdapters()) !== null && _this$getInspectorAda !== void 0 && _this$getInspectorAda.requests) { this.deps.start().plugins.data.search.showWarnings(this.getInspectorAdapters().requests, warning => { var _this$vis$type$suppre, _this$vis$type; if (warning.type === 'shard_failure' && warning.reason.type === 'unsupported_aggregation_on_downsampled_index') { warnings.push(warning.reason.reason || warning.message); return true; } if ((_this$vis$type$suppre = (_this$vis$type = this.vis.type).suppressWarnings) !== null && _this$vis$type$suppre !== void 0 && _this$vis$type$suppre.call(_this$vis$type)) { // if the vis type wishes to supress all warnings, return true so the default logic won't pick it up return true; } }); } if (this.warningDomNode) { (0, _reactDom.render)( /*#__PURE__*/_react.default.createElement(_public2.Warnings, { warnings: warnings || [] }), this.warningDomNode); } } /** * * @param {Element} domNode */ async render(domNode) { this.timeRange = _lodash.default.cloneDeep(this.input.timeRange); this.transferCustomizationsToUiState(); const div = document.createElement('div'); div.className = `visualize panel-content panel-content--fullWidth`; domNode.appendChild(div); const warningDiv = document.createElement('div'); warningDiv.className = 'visPanel__warnings'; domNode.appendChild(warningDiv); this.warningDomNode = warningDiv; this.domNode = div; super.render(this.domNode); (0, _reactDom.render)( /*#__PURE__*/_react.default.createElement(_public.KibanaThemeProvider, { theme$: (0, _services.getTheme)().theme$ }, /*#__PURE__*/_react.default.createElement("div", { className: "visChart__spinner" }, /*#__PURE__*/_react.default.createElement(_eui.EuiLoadingChart, { mono: true, size: "l" }))), this.domNode); const expressions = (0, _services.getExpressions)(); this.handler = await expressions.loader(this.domNode, undefined, { renderMode: this.input.renderMode || 'view', onRenderError: (element, error) => { this.onContainerError(error); }, executionContext: this.getExecutionContext() }); this.subscriptions.push(this.handler.events$.subscribe(async event => { if (!this.input.disableTriggers) { const triggerId = (0, _lodash.get)(_events.VIS_EVENT_TO_TRIGGER, event.name, _events.VIS_EVENT_TO_TRIGGER.filter); let context; if (triggerId === _events.VIS_EVENT_TO_TRIGGER.applyFilter) { var _this$vis$data$indexP2; context = { embeddable: this, timeFieldName: (_this$vis$data$indexP2 = this.vis.data.indexPattern) === null || _this$vis$data$indexP2 === void 0 ? void 0 : _this$vis$data$indexP2.timeFieldName, ...event.data }; } else { var _this$vis$data$indexP3; context = { embeddable: this, data: { timeFieldName: (_this$vis$data$indexP3 = this.vis.data.indexPattern) === null || _this$vis$data$indexP3 === void 0 ? void 0 : _this$vis$data$indexP3.timeFieldName, ...event.data } }; } (0, _services.getUiActions)().getTrigger(triggerId).exec(context); } })); if (this.vis.description) { div.setAttribute('data-description', this.vis.description); } div.setAttribute('data-test-subj', 'visualizationLoader'); div.setAttribute('data-shared-item', ''); this.subscriptions.push(this.handler.loading$.subscribe(this.onContainerLoading)); this.subscriptions.push(this.handler.data$.subscribe(this.onContainerData)); this.subscriptions.push(this.handler.render$.subscribe(this.onContainerRender)); this.subscriptions.push(this.getUpdated$().subscribe(() => { const { error } = this.getOutput(); if (error) { (0, _reactDom.render)(this.renderError(error), this.domNode); } })); await this.updateHandler(); } renderError(error) { if ((0, _utils.isFallbackDataView)(this.vis.data.indexPattern)) { var _this$input$renderMod; return /*#__PURE__*/_react.default.createElement(_visualization_missed_saved_object_error.VisualizationMissedSavedObjectError, { renderMode: (_this$input$renderMod = this.input.renderMode) !== null && _this$input$renderMod !== void 0 ? _this$input$renderMod : 'view', savedObjectMeta: { savedObjectType: this.vis.data.savedSearchId ? 'search' : _public4.DATA_VIEW_SAVED_OBJECT_TYPE }, application: (0, _services.getApplication)(), message: typeof error === 'string' ? error : error.message }); } return /*#__PURE__*/_react.default.createElement(_visualization_error.default, { error: error }); } destroy() { super.destroy(); this.subscriptions.forEach(s => s.unsubscribe()); this.vis.uiState.off('change', this.uiStateChangeHandler); this.vis.uiState.off('reload', this.reload); if (this.handler) { this.handler.destroy(); this.handler.getElement().remove(); } } getExecutionContext() { var _this$parent, _this$vis$id; const parentContext = ((_this$parent = this.parent) === null || _this$parent === void 0 ? void 0 : _this$parent.getInput().executionContext) || (0, _services.getExecutionContext)().get(); const child = { type: 'agg_based', name: this.vis.type.name, id: (_this$vis$id = this.vis.id) !== null && _this$vis$id !== void 0 ? _this$vis$id : 'new', description: this.vis.title || this.input.title || this.vis.type.name, url: this.output.editUrl }; return { ...parentContext, child }; } async updateHandler() { var _this$vis$type$getExp, _this$vis$type2; const context = this.getExecutionContext(); this.expressionVariables = await ((_this$vis$type$getExp = (_this$vis$type2 = this.vis.type).getExpressionVariables) === null || _this$vis$type$getExp === void 0 ? void 0 : _this$vis$type$getExp.call(_this$vis$type2, this.vis, this.timefilter)); this.expressionVariablesSubject.next(this.expressionVariables); const expressionParams = { searchContext: { timeRange: this.timeRange, query: this.input.query, filters: this.input.filters, disableShardWarnings: true }, variables: { embeddableTitle: this.getTitle(), ...this.expressionVariables }, searchSessionId: this.input.searchSessionId, syncColors: this.input.syncColors, syncTooltips: this.input.syncTooltips, syncCursor: this.input.syncCursor, uiState: this.vis.uiState, interactive: !this.input.disableTriggers, inspectorAdapters: this.inspectorAdapters, executionContext: context }; if (this.abortController) { this.abortController.abort(); } this.abortController = new AbortController(); const abortController = this.abortController; try { this.expression = await (0, _to_ast.toExpressionAst)(this.vis, { timefilter: this.timefilter, timeRange: this.timeRange, abortSignal: this.abortController.signal }); } catch (e) { this.onContainerError(e); } if (this.handler && !abortController.signal.aborted) { await this.handler.update(this.expression, expressionParams); } } supportedTriggers() { var _this$vis$type$getSup, _this$vis$type$getSup2, _this$vis$type3; return (_this$vis$type$getSup = (_this$vis$type$getSup2 = (_this$vis$type3 = this.vis.type).getSupportedTriggers) === null || _this$vis$type$getSup2 === void 0 ? void 0 : _this$vis$type$getSup2.call(_this$vis$type3, this.vis.params)) !== null && _this$vis$type$getSup !== void 0 ? _this$vis$type$getSup : []; } getExpressionVariables$() { return this.expressionVariablesSubject.asObservable(); } getExpressionVariables() { return this.expressionVariables; } } exports.VisualizeEmbeddable = VisualizeEmbeddable;