"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.MapEmbeddable = void 0; exports.getControlledBy = getControlledBy; var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); var _i18n = require("@kbn/i18n"); var _lodash = _interopRequireDefault(require("lodash")); var _react = _interopRequireDefault(require("react")); var _reactRedux = require("react-redux"); var _fastDeepEqual = _interopRequireDefault(require("fast-deep-equal")); var _reactDom = require("react-dom"); var _operators = require("rxjs/operators"); var _eui = require("@elastic/eui"); var _public = require("@kbn/kibana-react-plugin/public"); var _public2 = require("@kbn/embeddable-plugin/public"); var _public3 = require("@kbn/data-plugin/public"); var _public4 = require("@kbn/unified-search-plugin/public"); var _elasticsearch_util = require("../../common/elasticsearch_util"); var _actions = require("../actions"); var _ui_selectors = require("../selectors/ui_selectors"); var _non_serializable_instances = require("../reducers/non_serializable_instances"); var _map_selectors = require("../selectors/map_selectors"); var _constants = require("../../common/constants"); var _kibana_services = require("../kibana_services"); var _map_container = require("../connected_components/map_container"); var _map_page = require("../routes/map_page"); var _index_pattern_util = require("../index_pattern_util"); var _map_attribute_service = require("../map_attribute_service"); var _trigger_utils = require("../trigger_actions/trigger_utils"); var _wait_until_time_layers_load = require("../routes/map_page/map_app/wait_until_time_layers_load"); var _map_embeddables_singleton = require("./map_embeddables_singleton"); var _get_geo_fields_label = require("./get_geo_fields_label"); /* * 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. */ async function getChartsPaletteServiceGetColor() { const chartsService = (0, _kibana_services.getCharts)(); const paletteRegistry = chartsService ? await chartsService.palettes.getPalettes() : null; if (!paletteRegistry) { return null; } const paletteDefinition = paletteRegistry.get('default'); const chartConfiguration = { syncColors: true }; return value => { const series = [{ name: value, rankAtDepth: 0, totalSeriesAtDepth: 1 }]; const color = paletteDefinition.getCategoricalColor(series, chartConfiguration); return color ? color : '#3d3d3d'; }; } function getIsRestore(searchSessionId) { if (!searchSessionId) { return false; } const searchSessionOptions = (0, _kibana_services.getSearchService)().session.getSearchOptions(searchSessionId); return searchSessionOptions ? searchSessionOptions.isRestore : false; } function getControlledBy(id) { return `mapEmbeddablePanel${id}`; } class MapEmbeddable extends _public2.Embeddable { constructor(config, initialInput, parent) { super(initialInput, { editApp: _constants.APP_ID, editable: config.editable, indexPatterns: [] }, parent); (0, _defineProperty2.default)(this, "type", _constants.MAP_SAVED_OBJECT_TYPE); (0, _defineProperty2.default)(this, "deferEmbeddableLoad", true); (0, _defineProperty2.default)(this, "_isActive", void 0); (0, _defineProperty2.default)(this, "_savedMap", void 0); (0, _defineProperty2.default)(this, "_renderTooltipContent", void 0); (0, _defineProperty2.default)(this, "_subscriptions", []); (0, _defineProperty2.default)(this, "_prevIsRestore", false); (0, _defineProperty2.default)(this, "_prevMapExtent", void 0); (0, _defineProperty2.default)(this, "_prevSyncColors", void 0); (0, _defineProperty2.default)(this, "_domNode", void 0); (0, _defineProperty2.default)(this, "_unsubscribeFromStore", void 0); (0, _defineProperty2.default)(this, "_isInitialized", false); (0, _defineProperty2.default)(this, "_controlledBy", void 0); (0, _defineProperty2.default)(this, "_isSharable", true); (0, _defineProperty2.default)(this, "_onRenderComplete$", void 0); (0, _defineProperty2.default)(this, "setRenderTooltipContent", renderTooltipContent => { this._renderTooltipContent = renderTooltipContent; }); (0, _defineProperty2.default)(this, "setEventHandlers", eventHandlers => { this._savedMap.getStore().dispatch((0, _non_serializable_instances.setEventHandlers)(eventHandlers)); }); (0, _defineProperty2.default)(this, "_getIsMovementSynchronized", () => { return this.input.isMovementSynchronized === undefined ? true : this.input.isMovementSynchronized; }); (0, _defineProperty2.default)(this, "_getIsFilterByMapExtent", () => { return this.input.filterByMapExtent === undefined ? false : this.input.filterByMapExtent; }); (0, _defineProperty2.default)(this, "_propogateMapMovement", (lat, lon, zoom) => { if (this._getIsMovementSynchronized()) { _map_embeddables_singleton.mapEmbeddablesSingleton.setLocation(this.input.id, lat, lon, zoom); } }); (0, _defineProperty2.default)(this, "onSingleValueTrigger", (actionId, key, value) => { const action = (0, _kibana_services.getUiActions)().getAction(actionId); if (!action) { throw new Error('Unable to apply action, could not locate action'); } const executeContext = { ...this.getActionContext(), data: { data: (0, _trigger_utils.toValueClickDataFormat)(key, value) } }; action.execute(executeContext); }); (0, _defineProperty2.default)(this, "addFilters", async (filters, actionId = _public4.ACTION_GLOBAL_APPLY_FILTER) => { const executeContext = { ...this.getActionContext(), filters }; const action = (0, _kibana_services.getUiActions)().getAction(actionId); if (!action) { throw new Error('Unable to apply filter, could not locate action'); } action.execute(executeContext); }); (0, _defineProperty2.default)(this, "getFilterActions", async () => { const filterActions = await (0, _kibana_services.getUiActions)().getTriggerCompatibleActions(_public3.APPLY_FILTER_TRIGGER, { embeddable: this, filters: [] }); const valueClickActions = await (0, _kibana_services.getUiActions)().getTriggerCompatibleActions(_public2.VALUE_CLICK_TRIGGER, { embeddable: this, data: { // uiActions.getTriggerCompatibleActions validates action with provided context // so if event.key and event.value are used in the URL template but can not be parsed from context // then the action is filtered out. // To prevent filtering out actions, provide dummy context when initially fetching actions. data: (0, _trigger_utils.toValueClickDataFormat)('anyfield', 'anyvalue') } }); return [...filterActions, ...valueClickActions.filter(_trigger_utils.isUrlDrilldown)]; }); (0, _defineProperty2.default)(this, "getActionContext", () => { const trigger = (0, _kibana_services.getUiActions)().getTrigger(_public3.APPLY_FILTER_TRIGGER); if (!trigger) { throw new Error('Unable to get context, could not locate trigger'); } return { embeddable: this, trigger }; }); // Timing bug for dashboard with multiple maps with synchronized movement and filter by map extent enabled // When moving map with filterByMapExtent:false, previous map extent filter(s) does not get removed // Cuased by syncDashboardContainerInput applyContainerChangesToState. // 1) _setMapExtentFilter executes ACTION_GLOBAL_APPLY_FILTER action, // removing previous map extent filter and adding new map extent filter // 2) applyContainerChangesToState then re-adds stale input.filters (which contains previous map extent filter) // Add debounce to fix timing issue. // 1) applyContainerChangesToState now runs first and does its thing // 2) _setMapExtentFilter executes ACTION_GLOBAL_APPLY_FILTER action, // removing previous map extent filter and adding new map extent filter (0, _defineProperty2.default)(this, "_setMapExtentFilter", _lodash.default.debounce(() => { const mapExtent = (0, _map_selectors.getMapExtent)(this._savedMap.getStore().getState()); const geoFieldNames = _map_embeddables_singleton.mapEmbeddablesSingleton.getGeoFieldNames(); if (mapExtent === undefined || geoFieldNames.length === 0) { return; } this._prevMapExtent = mapExtent; const mapExtentFilter = (0, _elasticsearch_util.createExtentFilter)(mapExtent, geoFieldNames); mapExtentFilter.meta.controlledBy = this._controlledBy; mapExtentFilter.meta.alias = _i18n.i18n.translate('xpack.maps.embeddable.boundsFilterLabel', { defaultMessage: '{geoFieldsLabel} within map bounds', values: { geoFieldsLabel: (0, _get_geo_fields_label.getGeoFieldsLabel)(geoFieldNames) } }); const executeContext = { ...this.getActionContext(), filters: [mapExtentFilter], controlledBy: this._controlledBy }; const action = (0, _kibana_services.getUiActions)().getAction(_public4.ACTION_GLOBAL_APPLY_FILTER); if (!action) { throw new Error('Unable to apply map extent filter, could not locate action'); } action.execute(executeContext); }, 100)); (0, _defineProperty2.default)(this, "_mapSyncHandler", (lat, lon, zoom) => { // auto fit to bounds is not compatable with map synchronization // auto fit to bounds may cause map location to never stablize and bound back and forth between bounds on different maps if ((0, _map_selectors.getMapSettings)(this._savedMap.getStore().getState()).autoFitToDataBounds) { this._savedMap.getStore().dispatch((0, _actions.setMapSettings)({ autoFitToDataBounds: false })); } this._savedMap.getStore().dispatch((0, _actions.setGotoWithCenter)({ lat, lon, zoom })); }); this._isActive = true; this._savedMap = new _map_page.SavedMap({ mapEmbeddableInput: initialInput }); this._initializeSaveMap(); this._subscriptions.push(this.getUpdated$().subscribe(() => this.onUpdate())); this._controlledBy = getControlledBy(this.id); this._onRenderComplete$ = this.getOutput$().pipe( // wrapping distinctUntilChanged with startWith and skip to prime distinctUntilChanged with an initial value. (0, _operators.startWith)(this.getOutput()), (0, _operators.distinctUntilChanged)((a, b) => a.loading === b.loading), (0, _operators.skip)(1), (0, _operators.debounceTime)(_constants.RENDER_TIMEOUT), (0, _operators.filter)(output => !output.loading), (0, _operators.map)(() => { // Observable notifies subscriber when rendering is complete // Return void to not expose internal implemenation details of observabale return; })); } getOnRenderComplete$() { return this._onRenderComplete$; } reportsEmbeddableLoad() { return true; } async _initializeSaveMap() { try { await this._savedMap.whenReady(); } catch (e) { this.onFatalError(e); return; } this._initializeStore(); try { await this._initializeOutput(); } catch (e) { this.onFatalError(e); return; } this._savedMap.getStore().dispatch((0, _actions.setExecutionContext)(this.getExecutionContext())); // deferred loading of this embeddable is complete this.setInitializationFinished(); this._isInitialized = true; if (this._domNode) { this.render(this._domNode); } } getExecutionContext() { const parentContext = (0, _kibana_services.getExecutionContextService)().get(); const mapContext = { type: _constants.APP_ID, name: _constants.APP_ID, id: this.id, url: this.output.editPath }; return parentContext ? { ...parentContext, child: mapContext } : mapContext; } _initializeStore() { this._dispatchSetChartsPaletteServiceGetColor(this.input.syncColors); const store = this._savedMap.getStore(); store.dispatch((0, _actions.setReadOnly)(true)); store.dispatch((0, _actions.setMapSettings)({ keydownScrollZoom: true, showTimesliderToggleButton: false })); // Passing callback into redux store instead of regular pattern of getting redux state changes for performance reasons store.dispatch((0, _non_serializable_instances.setOnMapMove)(this._propogateMapMovement)); this._dispatchSetQuery({ forceRefresh: false }); this._subscriptions.push((0, _public2.shouldFetch$)(this.getUpdated$(), () => { return { ...this.getInput(), filters: this._getInputFilters(), searchSessionId: this._getSearchSessionId() }; }).subscribe(() => { this._dispatchSetQuery({ forceRefresh: false }); })); const mapStateJSON = this._savedMap.getAttributes().mapStateJSON; if (mapStateJSON) { try { const mapState = JSON.parse(mapStateJSON); store.dispatch((0, _actions.setEmbeddableSearchContext)({ filters: mapState.filters ? mapState.filters : [], query: mapState.query })); } catch (e) { // ignore malformed mapStateJSON, not a critical error for viewing map - map will just use defaults } } this._unsubscribeFromStore = store.subscribe(() => { this._handleStoreChanges(); }); } async _initializeOutput() { var _input$title; const { title: savedMapTitle, description: savedMapDescription } = this._savedMap.getAttributes(); const input = this.getInput(); const title = input.hidePanelTitles ? '' : (_input$title = input.title) !== null && _input$title !== void 0 ? _input$title : savedMapTitle; const savedObjectId = 'savedObjectId' in input ? input.savedObjectId : undefined; this.updateOutput({ defaultTitle: savedMapTitle, defaultDescription: savedMapDescription, title, editPath: (0, _constants.getEditPath)(savedObjectId), editUrl: (0, _kibana_services.getHttp)().basePath.prepend((0, _constants.getFullPath)(savedObjectId)), indexPatterns: await this._getIndexPatterns() }); } inputIsRefType(input) { return (0, _map_attribute_service.getMapAttributeService)().inputIsRefType(input); } async getInputAsRefType() { return (0, _map_attribute_service.getMapAttributeService)().getInputAsRefType(this.getExplicitInput(), { showSaveModal: true, saveModalTitle: this.getTitle() }); } async getExplicitInputIsEqual(lastExplicitInput) { const currentExplicitInput = this.getExplicitInput(); if (!(0, _public2.genericEmbeddableInputIsEqual)(lastExplicitInput, currentExplicitInput)) return false; // generic embeddable input is equal, now we compare map specific input elements, ignoring 'mapBuffer'. const lastMapInput = (0, _public2.omitGenericEmbeddableInput)(_lodash.default.omit(lastExplicitInput, 'mapBuffer')); const currentMapInput = (0, _public2.omitGenericEmbeddableInput)(_lodash.default.omit(currentExplicitInput, 'mapBuffer')); return (0, _fastDeepEqual.default)(lastMapInput, currentMapInput); } async getInputAsValueType() { return (0, _map_attribute_service.getMapAttributeService)().getInputAsValueType(this.getExplicitInput()); } getLayerList() { return (0, _map_selectors.getLayerList)(this._savedMap.getStore().getState()); } async getFilters() { const embeddableSearchContext = (0, _map_selectors.getEmbeddableSearchContext)(this._savedMap.getStore().getState()); return embeddableSearchContext ? embeddableSearchContext.filters : []; } async getQuery() { const embeddableSearchContext = (0, _map_selectors.getEmbeddableSearchContext)(this._savedMap.getStore().getState()); return embeddableSearchContext === null || embeddableSearchContext === void 0 ? void 0 : embeddableSearchContext.query; } supportedTriggers() { return [_public3.APPLY_FILTER_TRIGGER, _public2.VALUE_CLICK_TRIGGER]; } /* * Set to false to exclude sharing attributes 'data-*'. */ setIsSharable(isSharable) { this._isSharable = isSharable; } getInspectorAdapters() { return (0, _non_serializable_instances.getInspectorAdapters)(this._savedMap.getStore().getState()); } onUpdate() { if (this.input.syncColors !== this._prevSyncColors) { this._dispatchSetChartsPaletteServiceGetColor(this.input.syncColors); } const isRestore = getIsRestore(this._getSearchSessionId()); if (isRestore !== this._prevIsRestore) { this._prevIsRestore = isRestore; this._savedMap.getStore().dispatch((0, _actions.setMapSettings)({ disableInteractive: isRestore, hideToolbarOverlay: isRestore })); } } _gotoSynchronizedLocation() { const syncedLocation = _map_embeddables_singleton.mapEmbeddablesSingleton.getLocation(); if (syncedLocation) { // set map to synchronized view this._mapSyncHandler(syncedLocation.lat, syncedLocation.lon, syncedLocation.zoom); return; } if (!(0, _map_selectors.getMapReady)(this._savedMap.getStore().getState())) { // Initialize synchronized view to map's goto // Use goto because un-rendered map will not have accurate mapCenter and mapZoom. const goto = (0, _map_selectors.getGoto)(this._savedMap.getStore().getState()); if (goto && goto.center) { _map_embeddables_singleton.mapEmbeddablesSingleton.setLocation(this.input.id, goto.center.lat, goto.center.lon, goto.center.zoom); return; } } // Initialize synchronized view to map's view const center = (0, _map_selectors.getMapCenter)(this._savedMap.getStore().getState()); const zoom = (0, _map_selectors.getMapZoom)(this._savedMap.getStore().getState()); _map_embeddables_singleton.mapEmbeddablesSingleton.setLocation(this.input.id, center.lat, center.lon, zoom); } _getInputFilters() { return this.input.filters ? this.input.filters.filter(filter => !filter.meta.disabled && filter.meta.controlledBy !== this._controlledBy) : []; } _getSearchSessionId() { // New search session id causes all layers from elasticsearch to refetch data. // Dashboard provides a new search session id anytime filters change. // Thus, filtering embeddable container by map extent causes a new search session id any time the map is moved. // Disabling search session when filtering embeddable container by map extent. // The use case for search sessions (restoring results because of slow responses) does not match the use case of // filtering by map extent (rapid responses as users explore their map). return this.input.filterByMapExtent ? undefined : this.input.searchSessionId; } _dispatchSetQuery({ forceRefresh }) { this._savedMap.getStore().dispatch((0, _actions.setQuery)({ filters: this._getInputFilters(), query: this.input.query, timeFilters: this.input.timeRange, timeslice: this.input.timeslice ? { from: this.input.timeslice[0], to: this.input.timeslice[1] } : undefined, clearTimeslice: this.input.timeslice === undefined, forceRefresh, searchSessionId: this._getSearchSessionId(), searchSessionMapBuffer: getIsRestore(this._getSearchSessionId()) ? this.input.mapBuffer : undefined })); } async _dispatchSetChartsPaletteServiceGetColor(syncColors) { this._prevSyncColors = syncColors; const chartsPaletteServiceGetColor = syncColors ? await getChartsPaletteServiceGetColor() : null; if (syncColors !== this._prevSyncColors) { return; } this._savedMap.getStore().dispatch((0, _non_serializable_instances.setChartsPaletteServiceGetColor)(chartsPaletteServiceGetColor)); } /** * * @param {HTMLElement} domNode * @param {ContainerState} containerState */ render(domNode) { this._domNode = domNode; if (!this._isInitialized) { return; } _map_embeddables_singleton.mapEmbeddablesSingleton.register(this.input.id, { getTitle: () => { const output = this.getOutput(); if (output.title) { return output.title; } if (output.defaultTitle) { return output.defaultTitle; } return this.input.id; }, onLocationChange: this._mapSyncHandler, getIsMovementSynchronized: this._getIsMovementSynchronized, setIsMovementSynchronized: isMovementSynchronized => { this.updateInput({ isMovementSynchronized }); if (isMovementSynchronized) { this._gotoSynchronizedLocation(); } else if (!isMovementSynchronized && this._savedMap.getAutoFitToBounds()) { // restore autoFitToBounds when isMovementSynchronized disabled this._savedMap.getStore().dispatch((0, _actions.setMapSettings)({ autoFitToDataBounds: true })); } }, getIsFilterByMapExtent: this._getIsFilterByMapExtent, setIsFilterByMapExtent: isFilterByMapExtent => { this.updateInput({ filterByMapExtent: isFilterByMapExtent }); if (isFilterByMapExtent) { this._setMapExtentFilter(); } else { this._clearMapExtentFilter(); } }, getGeoFieldNames: () => { return (0, _map_selectors.getGeoFieldNames)(this._savedMap.getStore().getState()); } }); if (this._getIsMovementSynchronized()) { this._gotoSynchronizedLocation(); } const sharingSavedObjectProps = this._savedMap.getSharingSavedObjectProps(); const spaces = (0, _kibana_services.getSpacesApi)(); const content = sharingSavedObjectProps && spaces && (sharingSavedObjectProps === null || sharingSavedObjectProps === void 0 ? void 0 : sharingSavedObjectProps.outcome) === 'conflict' ? /*#__PURE__*/_react.default.createElement("div", { className: "mapEmbeddedError" }, /*#__PURE__*/_react.default.createElement(_eui.EuiEmptyPrompt, { iconType: "warning", iconColor: "danger", "data-test-subj": "embeddable-maps-failure", body: spaces.ui.components.getEmbeddableLegacyUrlConflict({ targetType: _constants.MAP_SAVED_OBJECT_TYPE, sourceId: sharingSavedObjectProps.sourceId }) })) : /*#__PURE__*/_react.default.createElement(_map_container.MapContainer, { onSingleValueTrigger: this.onSingleValueTrigger, addFilters: this.input.hideFilterActions || this.input.disableTriggers ? null : this.addFilters, getFilterActions: this.getFilterActions, getActionContext: this.getActionContext, renderTooltipContent: this._renderTooltipContent, title: this.getTitle(), description: this.getDescription(), waitUntilTimeLayersLoad$: (0, _wait_until_time_layers_load.waitUntilTimeLayersLoad$)(this._savedMap.getStore()), isSharable: this._isSharable }); const I18nContext = (0, _kibana_services.getCoreI18n)().Context; (0, _reactDom.render)( /*#__PURE__*/_react.default.createElement(_reactRedux.Provider, { store: this._savedMap.getStore() }, /*#__PURE__*/_react.default.createElement(I18nContext, null, /*#__PURE__*/_react.default.createElement(_public.KibanaThemeProvider, { theme$: (0, _kibana_services.getTheme)().theme$ }, content))), this._domNode); } setLayerList(layerList) { this._savedMap.getStore().dispatch((0, _actions.replaceLayerList)(layerList)); this._getIndexPatterns().then(indexPatterns => { this.updateOutput({ indexPatterns }); }); } updateLayerById(layerDescriptor) { this._savedMap.getStore().dispatch((0, _actions.updateLayerById)(layerDescriptor)); } async _getIndexPatterns() { const queryableIndexPatternIds = (0, _map_selectors.getQueryableUniqueIndexPatternIds)(this._savedMap.getStore().getState()); return await (0, _index_pattern_util.getIndexPatternsFromIds)(queryableIndexPatternIds); } _clearMapExtentFilter() { this._prevMapExtent = undefined; const executeContext = { ...this.getActionContext(), filters: [], controlledBy: this._controlledBy }; const action = (0, _kibana_services.getUiActions)().getAction(_public4.ACTION_GLOBAL_APPLY_FILTER); if (!action) { throw new Error('Unable to apply map extent filter, could not locate action'); } action.execute(executeContext); } destroy() { super.destroy(); _map_embeddables_singleton.mapEmbeddablesSingleton.unregister(this.input.id); this._isActive = false; if (this._unsubscribeFromStore) { this._unsubscribeFromStore(); } if (this._domNode) { (0, _reactDom.unmountComponentAtNode)(this._domNode); } this._subscriptions.forEach(subscription => { subscription.unsubscribe(); }); } reload() { this._dispatchSetQuery({ forceRefresh: true }); } _handleStoreChanges() { if (!this._isActive || !(0, _map_selectors.getMapReady)(this._savedMap.getStore().getState())) { return; } const mapExtent = (0, _map_selectors.getMapExtent)(this._savedMap.getStore().getState()); if (this._getIsFilterByMapExtent() && !_lodash.default.isEqual(this._prevMapExtent, mapExtent)) { this._setMapExtentFilter(); } const center = (0, _map_selectors.getMapCenter)(this._savedMap.getStore().getState()); const zoom = (0, _map_selectors.getMapZoom)(this._savedMap.getStore().getState()); const mapCenter = this.input.mapCenter || undefined; if (!mapCenter || mapCenter.lat !== center.lat || mapCenter.lon !== center.lon || mapCenter.zoom !== zoom) { this.updateInput({ mapCenter: { lat: center.lat, lon: center.lon, zoom }, mapBuffer: (0, _map_selectors.getMapBuffer)(this._savedMap.getStore().getState()) }); } const isLayerTOCOpen = (0, _ui_selectors.getIsLayerTOCOpen)(this._savedMap.getStore().getState()); if (this.input.isLayerTOCOpen !== isLayerTOCOpen) { this.updateInput({ isLayerTOCOpen }); } const openTOCDetails = (0, _ui_selectors.getOpenTOCDetails)(this._savedMap.getStore().getState()); if (!_lodash.default.isEqual(this.input.openTOCDetails, openTOCDetails)) { this.updateInput({ openTOCDetails }); } const hiddenLayerIds = (0, _map_selectors.getHiddenLayerIds)(this._savedMap.getStore().getState()); if (!_lodash.default.isEqual(this.input.hiddenLayers, hiddenLayerIds)) { this.updateInput({ hiddenLayers: hiddenLayerIds }); } const isLoading = (0, _map_selectors.isMapLoading)(this._savedMap.getStore().getState()); if (this.getOutput().loading !== isLoading) { /** * Maps emit rendered when the data is loaded, as we don't have feedback from the maps rendering library atm. * This means that the DASHBOARD_LOADED_EVENT event might be fired while a map is still rendering in some cases. * For more details please contact the maps team. */ this.updateOutput({ loading: isLoading, rendered: !isLoading // do not surface layer errors as output.error // output.error blocks entire embeddable display and prevents map from displaying // layer errors are better surfaced in legend while still keeping the map usable }); } } } exports.MapEmbeddable = MapEmbeddable;