"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.LensTopNavMenu = void 0; var _lodash = require("lodash"); var _i18n = require("@kbn/i18n"); var _react = _interopRequireWildcard(require("react")); var _esQuery = require("@kbn/es-query"); var _reactRedux = require("react-redux"); var _public = require("@kbn/data-plugin/public"); var _public2 = require("@kbn/kibana-react-plugin/public"); var _moment = _interopRequireDefault(require("moment")); var _locator = require("../../common/locator/locator"); var _constants = require("../../common/constants"); var _settings_menu = require("./settings_menu"); var _state_management = require("../state_management"); var _utils = require("../utils"); var _show_underlying_data = require("./show_underlying_data"); var _lens_slice = require("../state_management/lens_slice"); var _share_action = require("./share_action"); 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 getSaveButtonMeta({ contextFromEmbeddable, showSaveAndReturn, showReplaceInDashboard, showReplaceInCanvas }) { if (showSaveAndReturn) { return { label: contextFromEmbeddable ? _i18n.i18n.translate('xpack.lens.app.saveAndReplace', { defaultMessage: 'Save and replace' }) : _i18n.i18n.translate('xpack.lens.app.saveAndReturn', { defaultMessage: 'Save and return' }), emphasize: true, iconType: contextFromEmbeddable ? 'save' : 'checkInCircleFilled', testId: 'lnsApp_saveAndReturnButton', description: _i18n.i18n.translate('xpack.lens.app.saveAndReturnButtonAriaLabel', { defaultMessage: 'Save the current lens visualization and return to the last app' }) }; } if (showReplaceInDashboard) { return { label: _i18n.i18n.translate('xpack.lens.app.replaceInDashboard', { defaultMessage: 'Replace in dashboard' }), emphasize: true, iconType: 'merge', testId: 'lnsApp_replaceInDashboardButton', description: _i18n.i18n.translate('xpack.lens.app.replaceInDashboardButtonAriaLabel', { defaultMessage: 'Replace legacy visualization with lens visualization and return to the dashboard' }) }; } if (showReplaceInCanvas) { return { label: _i18n.i18n.translate('xpack.lens.app.replaceInCanvas', { defaultMessage: 'Replace in canvas' }), emphasize: true, iconType: 'merge', testId: 'lnsApp_replaceInCanvasButton', description: _i18n.i18n.translate('xpack.lens.app.replaceInCanvasButtonAriaLabel', { defaultMessage: 'Replace legacy visualization with lens visualization and return to the canvas' }) }; } } function getLensTopNavConfig(options) { const { actions, allowByValue, savingToLibraryPermitted, savingToDashboardPermitted, contextOriginatingApp, showReplaceInDashboard, showReplaceInCanvas, contextFromEmbeddable, isByValueMode } = options; const topNavMenu = []; const showSaveAndReturn = actions.saveAndReturn.visible; const enableSaveButton = savingToLibraryPermitted || allowByValue && savingToDashboardPermitted && !isByValueMode && !showSaveAndReturn; const saveButtonLabel = isByValueMode ? _i18n.i18n.translate('xpack.lens.app.addToLibrary', { defaultMessage: 'Save to library' }) : actions.saveAndReturn.visible ? _i18n.i18n.translate('xpack.lens.app.saveAs', { defaultMessage: 'Save as' }) : _i18n.i18n.translate('xpack.lens.app.save', { defaultMessage: 'Save' }); if (contextOriginatingApp && !actions.cancel.visible) { topNavMenu.push({ label: _i18n.i18n.translate('xpack.lens.app.goBackLabel', { defaultMessage: `Go back to {contextOriginatingApp}`, values: { contextOriginatingApp } }), run: actions.goBack.execute, className: 'lnsNavItem__withDivider', testId: 'lnsApp_goBackToAppButton', description: _i18n.i18n.translate('xpack.lens.app.goBackLabel', { defaultMessage: `Go back to {contextOriginatingApp}`, values: { contextOriginatingApp } }), disableButton: !actions.goBack.enabled }); } if (actions.getUnderlyingDataUrl.visible) { var _actions$getUnderlyin, _actions$getUnderlyin2; const exploreDataInDiscoverLabel = _i18n.i18n.translate('xpack.lens.app.exploreDataInDiscover', { defaultMessage: 'Explore data in Discover' }); topNavMenu.push({ label: exploreDataInDiscoverLabel, run: actions.getUnderlyingDataUrl.execute, testId: 'lnsApp_openInDiscover', className: 'lnsNavItem__withDivider', description: exploreDataInDiscoverLabel, disableButton: !actions.getUnderlyingDataUrl.enabled, tooltip: actions.getUnderlyingDataUrl.tooltip, target: '_blank', href: (_actions$getUnderlyin = (_actions$getUnderlyin2 = actions.getUnderlyingDataUrl).getLink) === null || _actions$getUnderlyin === void 0 ? void 0 : _actions$getUnderlyin.call(_actions$getUnderlyin2) }); } topNavMenu.push({ label: _i18n.i18n.translate('xpack.lens.app.inspect', { defaultMessage: 'Inspect' }), run: actions.inspect.execute, testId: 'lnsApp_inspectButton', description: _i18n.i18n.translate('xpack.lens.app.inspectAriaLabel', { defaultMessage: 'inspect' }), disableButton: false }); if (actions.share.visible) { topNavMenu.push({ label: _i18n.i18n.translate('xpack.lens.app.shareTitle', { defaultMessage: 'Share' }), run: actions.share.execute, testId: 'lnsApp_shareButton', description: _i18n.i18n.translate('xpack.lens.app.shareTitleAria', { defaultMessage: 'Share visualization' }), disableButton: !actions.share.enabled, tooltip: actions.share.tooltip }); } topNavMenu.push({ label: _i18n.i18n.translate('xpack.lens.app.settings', { defaultMessage: 'Settings' }), run: actions.openSettings.execute, className: 'lnsNavItem__withDivider', testId: 'lnsApp_settingsButton', description: _i18n.i18n.translate('xpack.lens.app.settingsAriaLabel', { defaultMessage: 'Open the Lens settings menu' }) }); if (actions.cancel.visible) { topNavMenu.push({ label: _i18n.i18n.translate('xpack.lens.app.cancel', { defaultMessage: 'Cancel' }), run: actions.cancel.execute, testId: 'lnsApp_cancelButton', description: _i18n.i18n.translate('xpack.lens.app.cancelButtonAriaLabel', { defaultMessage: 'Return to the last app without saving changes' }) }); } topNavMenu.push({ label: saveButtonLabel, iconType: (showReplaceInDashboard || showReplaceInCanvas ? false : !showSaveAndReturn) ? 'save' : undefined, emphasize: showReplaceInDashboard || showReplaceInCanvas ? false : !showSaveAndReturn, run: actions.showSaveModal.execute, testId: 'lnsApp_saveButton', description: _i18n.i18n.translate('xpack.lens.app.saveButtonAriaLabel', { defaultMessage: 'Save the current lens visualization' }), disableButton: !enableSaveButton }); const saveButtonMeta = getSaveButtonMeta({ showSaveAndReturn, showReplaceInDashboard, showReplaceInCanvas, contextFromEmbeddable }); if (saveButtonMeta) { topNavMenu.push({ ...saveButtonMeta, run: actions.saveAndReturn.execute, disableButton: !actions.saveAndReturn.enabled }); } return topNavMenu; } const LensTopNavMenu = ({ setHeaderActionMenu, initialInput, indicateNoData, lensInspector, setIsSaveModalVisible, getIsByValueMode, runSave, onAppLeave, redirectToOrigin, datasourceMap, visualizationMap, title, goBackToOriginatingApp, contextOriginatingApp, initialContextIsEmbedded, topNavMenuEntryGenerators, initialContext, theme$, indexPatternService, currentDoc, onTextBasedSavedAndExit, getUserMessages, shortUrlService, isCurrentStateDirty }) => { var _application$capabili, _currentIndexPattern$; const { data, navigation, uiSettings, application, attributeService, share, dashboardFeatureFlag, dataViewFieldEditor, dataViewEditor, dataViews: dataViewsService } = (0, _public2.useKibana)().services; const { isSaveable, isLinkedToOriginatingApp, query, activeData, savedQuery, activeDatasourceId, datasourceStates, visualization, filters, dataViews } = (0, _state_management.useLensSelector)(state => state.lens); const dispatch = (0, _state_management.useLensDispatch)(); const dispatchSetState = _react.default.useCallback(state => dispatch((0, _state_management.setState)(state)), [dispatch]); const [indexPatterns, setIndexPatterns] = (0, _react.useState)([]); const [currentIndexPattern, setCurrentIndexPattern] = (0, _react.useState)(); const [isOnTextBasedMode, setIsOnTextBasedMode] = (0, _react.useState)(false); const [rejectedIndexPatterns, setRejectedIndexPatterns] = (0, _react.useState)([]); const dispatchChangeIndexPattern = _react.default.useCallback(async dataViewOrId => { const indexPatternId = typeof dataViewOrId === 'string' ? dataViewOrId : dataViewOrId.id; const newIndexPatterns = await indexPatternService.ensureIndexPattern({ id: indexPatternId, cache: dataViews.indexPatterns }); dispatch((0, _lens_slice.changeIndexPattern)({ dataViews: { indexPatterns: newIndexPatterns }, datasourceIds: Object.keys(datasourceStates), visualizationIds: visualization.activeId ? [visualization.activeId] : [], indexPatternId })); }, [dataViews.indexPatterns, datasourceStates, dispatch, indexPatternService, visualization.activeId]); const canEditDataView = Boolean(dataViewEditor === null || dataViewEditor === void 0 ? void 0 : dataViewEditor.userPermissions.editDataView()) || !(currentIndexPattern !== null && currentIndexPattern !== void 0 && currentIndexPattern.isPersisted()); const closeFieldEditor = (0, _react.useRef)(); const closeDataViewEditor = (0, _react.useRef)(); const allLoaded = Object.values(datasourceStates).every(({ isLoading }) => isLoading === false); (0, _react.useEffect)(() => { const activeDatasource = datasourceMap && activeDatasourceId && !datasourceStates[activeDatasourceId].isLoading ? datasourceMap[activeDatasourceId] : undefined; if (!activeDatasource) { return; } const indexPatternIds = new Set((0, _utils.getIndexPatternsIds)({ activeDatasources: Object.keys(datasourceStates).reduce((acc, datasourceId) => ({ ...acc, [datasourceId]: datasourceMap[datasourceId] }), {}), datasourceStates, visualizationState: visualization.state, activeVisualization: visualization.activeId ? visualizationMap[visualization.activeId] : undefined })); // Add ad-hoc data views from the Lens state even if they are not used Object.values(dataViews.indexPatterns).filter(indexPattern => !indexPattern.isPersisted).forEach(indexPattern => { indexPatternIds.add(indexPattern.id); }); const hasIndexPatternsChanged = indexPatterns.length + rejectedIndexPatterns.length !== indexPatternIds.size || [...indexPatternIds].some(id => ![...indexPatterns.map(ip => ip.id), ...rejectedIndexPatterns].find(loadedId => loadedId === id)); // Update the cached index patterns if the user made a change to any of them if (hasIndexPatternsChanged) { (0, _utils.getIndexPatternsObjects)([...indexPatternIds], dataViewsService).then(({ indexPatterns: indexPatternObjects, rejectedIds }) => { setIndexPatterns(indexPatternObjects); setRejectedIndexPatterns(rejectedIds); }); } }, [datasourceStates, activeDatasourceId, rejectedIndexPatterns, datasourceMap, visualizationMap, visualization, indexPatterns, dataViewsService, dataViews]); (0, _react.useEffect)(() => { const setCurrentPattern = async () => { if (activeDatasourceId && datasourceStates[activeDatasourceId].state) { const dataViewId = datasourceMap[activeDatasourceId].getUsedDataView(datasourceStates[activeDatasourceId].state); const dataView = dataViewId ? await data.dataViews.get(dataViewId) : undefined; setCurrentIndexPattern(dataView !== null && dataView !== void 0 ? dataView : indexPatterns[0]); } }; setCurrentPattern(); }, [activeDatasourceId, datasourceMap, datasourceStates, indexPatterns, data.dataViews, isOnTextBasedMode]); (0, _react.useEffect)(() => { if (typeof query === 'object' && query !== null && (0, _esQuery.isOfAggregateQueryType)(query)) { setIsOnTextBasedMode(true); } }, [query]); (0, _react.useEffect)(() => { return () => { var _closeFieldEditor$cur, _closeDataViewEditor$; // Make sure to close the editors when unmounting (_closeFieldEditor$cur = closeFieldEditor.current) === null || _closeFieldEditor$cur === void 0 ? void 0 : _closeFieldEditor$cur.call(closeFieldEditor); (_closeDataViewEditor$ = closeDataViewEditor.current) === null || _closeDataViewEditor$ === void 0 ? void 0 : _closeDataViewEditor$.call(closeDataViewEditor); }; }, []); const { AggregateQueryTopNavMenu } = navigation.ui; const { from, to } = data.query.timefilter.timefilter.getTime(); const savingToLibraryPermitted = Boolean(isSaveable && application.capabilities.visualize.save); const savingToDashboardPermitted = Boolean(isSaveable && ((_application$capabili = application.capabilities.dashboard) === null || _application$capabili === void 0 ? void 0 : _application$capabili.showWriteControls)); const defaultLensTitle = _i18n.i18n.translate('xpack.lens.app.share.defaultDashboardTitle', { defaultMessage: 'Lens Visualization [{date}]', values: { date: (0, _moment.default)().toISOString(true) } }); const additionalMenuEntries = (0, _react.useMemo)(() => { if (!visualization.activeId) return undefined; const visualizationId = visualization.activeId; const entries = topNavMenuEntryGenerators.flatMap(menuEntryGenerator => { const menuEntry = menuEntryGenerator({ datasourceStates, visualizationId, visualizationState: visualization.state, query, filters, initialContext, currentDoc }); return menuEntry ? [menuEntry] : []; }); if (entries.length > 0) { return entries; } }, [datasourceStates, topNavMenuEntryGenerators, visualization.activeId, visualization.state, query, filters, initialContext, currentDoc]); const discoverLocator = share === null || share === void 0 ? void 0 : share.url.locators.get('DISCOVER_APP_LOCATOR'); const layerMetaInfo = (0, _react.useMemo)(() => { if (!activeDatasourceId || !discoverLocator) { return; } if (visualization.activeId == null) { return; } return (0, _show_underlying_data.getLayerMetaInfo)(datasourceMap[activeDatasourceId], datasourceStates[activeDatasourceId].state, visualizationMap[visualization.activeId], visualization.state, activeData, dataViews.indexPatterns, data.query.timefilter.timefilter.getTime(), application.capabilities); }, [activeDatasourceId, discoverLocator, visualization, datasourceMap, datasourceStates, visualizationMap, activeData, dataViews.indexPatterns, data.query.timefilter.timefilter, application.capabilities]); const lensStore = (0, _reactRedux.useStore)(); const adHocDataViews = indexPatterns.filter(pattern => !pattern.isPersisted()); const topNavConfig = (0, _react.useMemo)(() => { const showReplaceInDashboard = (initialContext === null || initialContext === void 0 ? void 0 : initialContext.originatingApp) === 'dashboards' && !(initialInput !== null && initialInput !== void 0 && initialInput.savedObjectId); const showReplaceInCanvas = (initialContext === null || initialContext === void 0 ? void 0 : initialContext.originatingApp) === 'canvas' && !(initialInput !== null && initialInput !== void 0 && initialInput.savedObjectId); const contextFromEmbeddable = initialContext && 'isEmbeddable' in initialContext && initialContext.isEmbeddable; const showSaveAndReturn = !(showReplaceInDashboard || showReplaceInCanvas) && (Boolean(isLinkedToOriginatingApp && ( // Temporarily required until the 'by value' paradigm is default. dashboardFeatureFlag.allowByValueEmbeddables || Boolean(initialInput))) || Boolean(initialContextIsEmbedded)); const hasData = Boolean(activeData && Object.keys(activeData).length); const csvEnabled = Boolean(isSaveable && hasData); const shareUrlEnabled = Boolean(application.capabilities.visualize.createShortUrl && hasData); const showShareMenu = csvEnabled || shareUrlEnabled; const baseMenuEntries = getLensTopNavConfig({ isByValueMode: getIsByValueMode(), allowByValue: dashboardFeatureFlag.allowByValueEmbeddables, savingToLibraryPermitted, savingToDashboardPermitted, isSaveable, contextOriginatingApp, showReplaceInDashboard, showReplaceInCanvas, contextFromEmbeddable, actions: { inspect: { visible: true, execute: () => lensInspector.inspect({ title }) }, share: { visible: true, enabled: showShareMenu, tooltip: () => { if (!showShareMenu) { return _i18n.i18n.translate('xpack.lens.app.shareButtonDisabledWarning', { defaultMessage: 'The visualization has no data to share.' }); } }, execute: async anchorElement => { var _visualizationMap$vis, _visualizationMap$vis2, _visualizationMap$vis3; if (!share) { return; } if (visualization.activeId == null || !visualizationMap[visualization.activeId]) { return; } const { shareableUrl, savedObjectURL, reportingLocatorParams: locatorParams } = await (0, _share_action.getShareURL)(shortUrlService, { application, data }, { filters, query, activeDatasourceId, datasourceStates, datasourceMap, visualizationMap, visualization, currentDoc, adHocDataViews: adHocDataViews.map(dataView => dataView.toSpec()) }, shareUrlEnabled, isCurrentStateDirty); const sharingData = { activeData, csvEnabled, reportingDisabled: !csvEnabled, title: title || defaultLensTitle, locatorParams: { id: _locator.LENS_APP_LOCATOR, params: locatorParams }, layout: { dimensions: (_visualizationMap$vis = (_visualizationMap$vis2 = (_visualizationMap$vis3 = visualizationMap[visualization.activeId]).getReportingLayout) === null || _visualizationMap$vis2 === void 0 ? void 0 : _visualizationMap$vis2.call(_visualizationMap$vis3, visualization.state)) !== null && _visualizationMap$vis !== void 0 ? _visualizationMap$vis : _share_action.DEFAULT_LENS_LAYOUT_DIMENSIONS } }; share.toggleShareContextMenu({ anchorElement, allowEmbed: false, allowShortUrl: false, // we'll manage this implicitly via the new service shareableUrl: shareableUrl || '', shareableUrlForSavedObject: savedObjectURL.href, objectId: currentDoc === null || currentDoc === void 0 ? void 0 : currentDoc.savedObjectId, objectType: 'lens', objectTypeTitle: _i18n.i18n.translate('xpack.lens.app.share.panelTitle', { defaultMessage: 'visualization' }), sharingData, isDirty: isCurrentStateDirty, // disable the menu if both shortURL permission and the visualization has not been saved // TODO: improve here the disabling state with more specific checks disabledShareUrl: Boolean(!shareUrlEnabled && !(currentDoc !== null && currentDoc !== void 0 && currentDoc.savedObjectId)), showPublicUrlSwitch: () => false, onClose: () => { anchorElement === null || anchorElement === void 0 ? void 0 : anchorElement.focus(); } }); } }, saveAndReturn: { visible: showSaveAndReturn, enabled: isSaveable, execute: () => { if (isSaveable) { var _ref; // disabling the validation on app leave because the document has been saved. onAppLeave(actions => { return actions.default(); }); runSave({ newTitle: title || (contextFromEmbeddable ? _i18n.i18n.translate('xpack.lens.app.convertedLabel', { defaultMessage: '{title} (converted)', values: { title: initialContext.title || `${initialContext.visTypeTitle} visualization` } }) : ''), newCopyOnSave: false, isTitleDuplicateConfirmed: false, returnToOrigin: true, newDescription: contextFromEmbeddable ? initialContext.description : '', panelTimeRange: contextFromEmbeddable ? initialContext.panelTimeRange : undefined }, { saveToLibrary: (_ref = initialInput && attributeService.inputIsRefType(initialInput)) !== null && _ref !== void 0 ? _ref : false }); } } }, showSaveModal: { visible: Boolean(savingToDashboardPermitted || savingToLibraryPermitted), execute: () => { if (savingToDashboardPermitted || savingToLibraryPermitted) { setIsSaveModalVisible(true); } } }, goBack: { visible: Boolean(contextOriginatingApp), enabled: Boolean(contextOriginatingApp), execute: () => { if (contextOriginatingApp) { goBackToOriginatingApp === null || goBackToOriginatingApp === void 0 ? void 0 : goBackToOriginatingApp(); } } }, cancel: { visible: Boolean(isLinkedToOriginatingApp), execute: () => { if (redirectToOrigin) { redirectToOrigin(); } } }, getUnderlyingDataUrl: { visible: Boolean(layerMetaInfo === null || layerMetaInfo === void 0 ? void 0 : layerMetaInfo.isVisible), enabled: !(layerMetaInfo !== null && layerMetaInfo !== void 0 && layerMetaInfo.error), tooltip: () => { return layerMetaInfo === null || layerMetaInfo === void 0 ? void 0 : layerMetaInfo.error; }, execute: () => {}, getLink: () => { var _dataViews$indexPatte; if (!layerMetaInfo) { return; } const { error, meta } = layerMetaInfo; // If Discover is not available, return // If there's no data, return if (error || !discoverLocator || !meta) { return; } const { filters: newFilters, query: newQuery } = (0, _show_underlying_data.combineQueryAndFilters)(query, filters, meta, indexPatterns, (0, _public.getEsQueryConfig)(uiSettings)); return discoverLocator.getRedirectUrl({ dataViewSpec: (_dataViews$indexPatte = dataViews.indexPatterns[meta.id]) === null || _dataViews$indexPatte === void 0 ? void 0 : _dataViews$indexPatte.spec, timeRange: data.query.timefilter.timefilter.getTime(), filters: newFilters, query: isOnTextBasedMode ? query : newQuery, columns: meta.columns }); } }, openSettings: { visible: true, execute: anchorElement => (0, _settings_menu.toggleSettingsMenuOpen)({ lensStore, anchorElement, theme$ }) } } }); return [...(additionalMenuEntries || []), ...baseMenuEntries]; }, [initialContext, initialInput, isLinkedToOriginatingApp, dashboardFeatureFlag.allowByValueEmbeddables, initialContextIsEmbedded, activeData, isSaveable, application, getIsByValueMode, savingToLibraryPermitted, savingToDashboardPermitted, contextOriginatingApp, layerMetaInfo, additionalMenuEntries, lensInspector, title, share, shortUrlService, data, filters, query, activeDatasourceId, datasourceStates, datasourceMap, visualizationMap, visualization, currentDoc, adHocDataViews, defaultLensTitle, isCurrentStateDirty, onAppLeave, runSave, attributeService, setIsSaveModalVisible, goBackToOriginatingApp, redirectToOrigin, discoverLocator, indexPatterns, uiSettings, dataViews.indexPatterns, isOnTextBasedMode, lensStore, theme$]); const onQuerySubmitWrapped = (0, _react.useCallback)(payload => { const { dateRange, query: newQuery } = payload; const currentRange = data.query.timefilter.timefilter.getTime(); if (dateRange.from !== currentRange.from || dateRange.to !== currentRange.to) { data.query.timefilter.timefilter.setTime(dateRange); } else { // Query has changed, renew the session id. // recalculate resolvedDateRange (relevant for relative time range) dispatchSetState({ searchSessionId: data.search.session.start(), resolvedDateRange: (0, _utils.getResolvedDateRange)(data.query.timefilter.timefilter) }); } if (newQuery) { if (!(0, _lodash.isEqual)(newQuery, query)) { dispatchSetState({ query: newQuery }); // check if query is text-based (sql, essql etc) and switchAndCleanDatasource if ((0, _esQuery.isOfAggregateQueryType)(newQuery) && !isOnTextBasedMode) { setIsOnTextBasedMode(true); dispatch((0, _state_management.switchAndCleanDatasource)({ newDatasourceId: 'textBased', visualizationId: visualization === null || visualization === void 0 ? void 0 : visualization.activeId, currentIndexPatternId: currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.id })); } } } }, [currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.id, data.query.timefilter.timefilter, data.search.session, dispatch, dispatchSetState, isOnTextBasedMode, query, visualization === null || visualization === void 0 ? void 0 : visualization.activeId]); const onSavedWrapped = (0, _react.useCallback)(newSavedQuery => { dispatchSetState({ savedQuery: newSavedQuery }); }, [dispatchSetState]); const onSavedQueryUpdatedWrapped = (0, _react.useCallback)(newSavedQuery => { const savedQueryFilters = newSavedQuery.attributes.filters || []; const globalFilters = data.query.filterManager.getGlobalFilters(); data.query.filterManager.setFilters([...globalFilters, ...savedQueryFilters]); dispatchSetState({ query: newSavedQuery.attributes.query, savedQuery: { ...newSavedQuery } }); // Shallow query for reference issues }, [data.query.filterManager, dispatchSetState]); const onClearSavedQueryWrapped = (0, _react.useCallback)(() => { data.query.filterManager.setFilters(data.query.filterManager.getGlobalFilters()); dispatchSetState({ filters: data.query.filterManager.getGlobalFilters(), query: data.query.queryString.getDefaultQuery(), savedQuery: undefined }); }, [data.query.filterManager, data.query.queryString, dispatchSetState]); const refreshFieldList = (0, _react.useCallback)(async () => { if (currentIndexPattern !== null && currentIndexPattern !== void 0 && currentIndexPattern.id) { (0, _utils.refreshIndexPatternsList)({ activeDatasources: Object.keys(datasourceStates).reduce((acc, datasourceId) => ({ ...acc, [datasourceId]: datasourceMap[datasourceId] }), {}), indexPatternId: currentIndexPattern.id, indexPatternService, indexPatternsCache: dataViews.indexPatterns }); } // start a new session so all charts are refreshed data.search.session.start(); }, [currentIndexPattern, data.search.session, datasourceMap, datasourceStates, indexPatternService, dataViews.indexPatterns]); const editField = (0, _react.useMemo)(() => canEditDataView ? async (fieldName, uiAction = 'edit') => { if (currentIndexPattern !== null && currentIndexPattern !== void 0 && currentIndexPattern.id) { const indexPatternInstance = await data.dataViews.get(currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.id); closeFieldEditor.current = dataViewFieldEditor.openEditor({ ctx: { dataView: indexPatternInstance }, fieldName, onSave: () => { if (indexPatternInstance.isPersisted()) { refreshFieldList(); } else { indexPatternService.replaceDataViewId(indexPatternInstance); } } }); } } : undefined, [canEditDataView, currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.id, data.dataViews, dataViewFieldEditor, indexPatternService, refreshFieldList]); const addField = (0, _react.useMemo)(() => canEditDataView && editField ? () => editField(undefined, 'add') : undefined, [editField, canEditDataView]); const createNewDataView = (0, _react.useCallback)(() => { closeDataViewEditor.current = dataViewEditor.openEditor({ onSave: async dataView => { if (dataView.id) { if (isOnTextBasedMode) { dispatch((0, _state_management.switchAndCleanDatasource)({ newDatasourceId: 'formBased', visualizationId: visualization === null || visualization === void 0 ? void 0 : visualization.activeId, currentIndexPatternId: dataView === null || dataView === void 0 ? void 0 : dataView.id })); } dispatchChangeIndexPattern(dataView); setCurrentIndexPattern(dataView); } }, allowAdHocDataView: true }); }, [dataViewEditor, dispatch, dispatchChangeIndexPattern, isOnTextBasedMode, visualization === null || visualization === void 0 ? void 0 : visualization.activeId]); const onCreateDefaultAdHocDataView = (0, _react.useCallback)(async dataViewSpec => { var _dataView$fields$getB; const dataView = await dataViewsService.create(dataViewSpec); if (((_dataView$fields$getB = dataView.fields.getByName('@timestamp')) === null || _dataView$fields$getB === void 0 ? void 0 : _dataView$fields$getB.type) === 'date') { dataView.timeFieldName = '@timestamp'; } if (isOnTextBasedMode) { dispatch((0, _state_management.switchAndCleanDatasource)({ newDatasourceId: 'formBased', visualizationId: visualization === null || visualization === void 0 ? void 0 : visualization.activeId, currentIndexPatternId: dataView === null || dataView === void 0 ? void 0 : dataView.id })); } dispatchChangeIndexPattern(dataView); setCurrentIndexPattern(dataView); }, [dataViewsService, dispatch, dispatchChangeIndexPattern, isOnTextBasedMode, visualization === null || visualization === void 0 ? void 0 : visualization.activeId]); const dataViewPickerProps = { trigger: { label: (currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : (_currentIndexPattern$ = currentIndexPattern.getName) === null || _currentIndexPattern$ === void 0 ? void 0 : _currentIndexPattern$.call(currentIndexPattern)) || '', 'data-test-subj': 'lns-dataView-switch-link', title: (currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.title) || '' }, currentDataViewId: currentIndexPattern === null || currentIndexPattern === void 0 ? void 0 : currentIndexPattern.id, onAddField: addField, onDataViewCreated: createNewDataView, onCreateDefaultAdHocDataView, adHocDataViews, onChangeDataView: async newIndexPatternId => { const currentDataView = await data.dataViews.get(newIndexPatternId); setCurrentIndexPattern(currentDataView); dispatchChangeIndexPattern(newIndexPatternId); if (isOnTextBasedMode) { dispatch((0, _state_management.switchAndCleanDatasource)({ newDatasourceId: 'formBased', visualizationId: visualization === null || visualization === void 0 ? void 0 : visualization.activeId, currentIndexPatternId: newIndexPatternId })); setIsOnTextBasedMode(false); } }, onEditDataView: async updatedDataViewStub => { if (!currentIndexPattern) return; if (currentIndexPattern.isPersisted()) { // clear instance cache and fetch again to make sure fields are up to date (in case pattern changed) dataViewsService.clearInstanceCache(currentIndexPattern.id); const updatedCurrentIndexPattern = await dataViewsService.get(currentIndexPattern.id); // if the data view was persisted, reload it from cache const updatedCache = { ...dataViews.indexPatterns }; delete updatedCache[currentIndexPattern.id]; const newIndexPatterns = await indexPatternService.ensureIndexPattern({ id: updatedCurrentIndexPattern.id, cache: updatedCache }); dispatch((0, _lens_slice.changeIndexPattern)({ dataViews: { indexPatterns: newIndexPatterns }, indexPatternId: updatedCurrentIndexPattern.id })); // Renew session id to make sure the request is done again dispatchSetState({ searchSessionId: data.search.session.start(), resolvedDateRange: (0, _utils.getResolvedDateRange)(data.query.timefilter.timefilter) }); // update list of index patterns to pick up mutations in the changed data view setCurrentIndexPattern(updatedCurrentIndexPattern); } else { // if it was an ad-hoc data view, we need to switch to a new data view anyway indexPatternService.replaceDataViewId(updatedDataViewStub); } } }; const textBasedLanguageModeErrors = getUserMessages('textBasedLanguagesQueryInput', { severity: 'error' }).map(({ shortMessage }) => new Error(shortMessage)); return /*#__PURE__*/_react.default.createElement(AggregateQueryTopNavMenu, { setMenuMountPoint: setHeaderActionMenu, config: topNavConfig, showSaveQuery: Boolean(application.capabilities.visualize.saveQuery), savedQuery: savedQuery, onQuerySubmit: onQuerySubmitWrapped, onSaved: onSavedWrapped, onSavedQueryUpdated: onSavedQueryUpdatedWrapped, onClearSavedQuery: onClearSavedQueryWrapped, indexPatterns: indexPatterns, query: query, dateRangeFrom: from, dateRangeTo: to, indicateNoData: indicateNoData, showSearchBar: true, dataViewPickerComponentProps: dataViewPickerProps, showDatePicker: indexPatterns.some(ip => ip.isTimeBased()) || // always show the timepicker for text based languages isOnTextBasedMode || Boolean(allLoaded && activeDatasourceId && datasourceMap[activeDatasourceId].isTimeBased(datasourceStates[activeDatasourceId].state, dataViews.indexPatterns)), textBasedLanguageModeErrors: textBasedLanguageModeErrors, onTextBasedSavedAndExit: onTextBasedSavedAndExit, showFilterBar: true, "data-test-subj": "lnsApp_topNav", screenTitle: 'lens', appName: _constants.LENS_APP_NAME, displayStyle: "detached", className: "hide-for-sharing" }); }; exports.LensTopNavMenu = LensTopNavMenu;