From c8f3527eba2608912e87104f46294142b003d6ec Mon Sep 17 00:00:00 2001 From: sulemanof Date: Mon, 9 Mar 2020 21:03:25 +0300 Subject: [PATCH 1/4] Fix linked search behavior --- .../visualize/np_ready/editor/editor.js | 57 ++--------- .../editor/lib/handle_saved_search.ts | 94 +++++++++++++++++++ .../visualize/np_ready/editor/lib/index.ts | 1 + .../editor/lib/visualize_app_state.ts | 8 +- .../public/visualize/np_ready/types.d.ts | 2 +- .../public/state_management/url/index.ts | 1 + .../state_management/url/kbn_url_storage.ts | 7 ++ .../create_kbn_url_state_storage.ts | 11 ++- 8 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index e1a20e3381331..6a9b94c6556fc 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -25,7 +25,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { makeStateful, useVisualizeAppState } from './lib'; +import { makeStateful, useVisualizeAppState, handleSavedSearch } from './lib'; import { VisualizeConstants } from '../visualize_constants'; import { getEditBreadcrumbs } from '../breadcrumbs'; @@ -488,6 +488,15 @@ function VisualizeAppController( }) ); + // handle linked search updates, such as link/unlink a saved search + handleSavedSearch({ + kbnUrlStateStorage, + savedVis, + stateContainer, + toastNotifications, + vis, + }); + $scope.$on('$destroy', () => { if ($scope._handler) { $scope._handler.destroy(); @@ -558,20 +567,6 @@ function VisualizeAppController( updateStateFromSavedQuery(savedQuery); }; - $scope.$watch('linked', linked => { - if (linked && !savedVis.savedSearchId) { - savedVis.savedSearchId = savedVis.searchSource.id; - vis.savedSearchId = savedVis.searchSource.id; - - $scope.$broadcast('render'); - } else if (!linked && savedVis.savedSearchId) { - delete savedVis.savedSearchId; - delete vis.savedSearchId; - - $scope.$broadcast('render'); - } - }); - /** * Called when the user clicks "Save" button. */ @@ -662,36 +657,6 @@ function VisualizeAppController( ); } - const unlinkFromSavedSearch = () => { - const searchSourceParent = searchSource.getParent(); - const searchSourceGrandparent = searchSourceParent.getParent(); - - delete savedVis.savedSearchId; - delete vis.savedSearchId; - searchSourceParent.setField( - 'filter', - _.union(searchSource.getOwnField('filter'), searchSourceParent.getOwnField('filter')) - ); - - stateContainer.transitions.unlinkSavedSearch( - searchSourceParent.getField('query'), - searchSourceParent.getField('filter') - ); - searchSource.setField('index', searchSourceParent.getField('index')); - searchSource.setParent(searchSourceGrandparent); - - toastNotifications.addSuccess( - i18n.translate('kbn.visualize.linkedToSearch.unlinkSuccessNotificationText', { - defaultMessage: `Unlinked from saved search '{searchTitle}'`, - values: { - searchTitle: savedVis.savedSearch.title, - }, - }) - ); - - $scope.fetch(); - }; - $scope.getAdditionalMessage = () => { return ( '' + @@ -703,8 +668,6 @@ function VisualizeAppController( ); }; - vis.on('unlinkFromSavedSearch', unlinkFromSavedSearch); - addHelpMenuToAppChrome(chrome, docLinks); init(); diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts new file mode 100644 index 0000000000000..cb892d278daed --- /dev/null +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts @@ -0,0 +1,94 @@ +/* + * Licensed to Elasticsearch B.V. under one or more contributor + * license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright + * ownership. Elasticsearch B.V. licenses this file to you under + * the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { i18n } from '@kbn/i18n'; + +import { ToastsStart } from 'kibana/public'; +import { Vis, VisSavedObject } from 'src/legacy/core_plugins/visualizations/public'; +import { Filter } from 'src/plugins/data/public'; +import { + IKbnUrlStateStorage, + ReduxLikeStateContainer, +} from '../../../../../../../../plugins/kibana_utils/public'; +import { VisualizeAppStateTransitions, VisualizeAppState } from '../../types'; + +interface Arguments { + kbnUrlStateStorage: IKbnUrlStateStorage; + savedVis: VisSavedObject; + stateContainer: ReduxLikeStateContainer; + toastNotifications: ToastsStart; + vis: Vis; +} + +/** + * Handles changes around linked search to a saved object + */ +export const handleSavedSearch = ({ + kbnUrlStateStorage, + savedVis, + stateContainer, + toastNotifications, + vis, +}: Arguments) => { + const { searchSource } = savedVis; + const searchSourceParent = searchSource.getParent(); + const searchSourceGrandparent = searchSourceParent?.getParent(); + + kbnUrlStateStorage.change$('savedSearchId').subscribe(savedSearchId => { + if (savedSearchId && !savedVis.savedSearchId) { + savedVis.savedSearchId = savedSearchId; + vis.savedSearchId = savedSearchId; + + searchSource.setParent(searchSourceParent); + } else if (!savedSearchId && savedVis.savedSearchId) { + delete savedVis.savedSearchId; + delete vis.savedSearchId; + } + }); + + const unlinkFromSavedSearch = () => { + if (!searchSourceParent) { + return; + } + + const currentIndex = searchSourceParent.getField('index'); + + kbnUrlStateStorage.remove('savedSearchId'); + kbnUrlStateStorage.set('indexPattern', currentIndex?.id); + + searchSource.setField('index', currentIndex); + searchSource.setParent(searchSourceGrandparent); + + stateContainer.transitions.unlinkSavedSearch({ + query: searchSourceParent.getField('query'), + parentFilters: searchSourceParent.getOwnField('filter') as Filter[], + }); + + toastNotifications.addSuccess( + i18n.translate('kbn.visualize.linkedToSearch.unlinkSuccessNotificationText', { + defaultMessage: `Unlinked from saved search '{searchTitle}'`, + values: { + searchTitle: savedVis.savedSearch?.title, + }, + }) + ); + }; + + vis.on('unlinkFromSavedSearch', unlinkFromSavedSearch); +}; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts index fa5b91b00edaf..c7aad0286308b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts @@ -19,3 +19,4 @@ export { useVisualizeAppState } from './visualize_app_state'; export { makeStateful } from './make_stateful'; +export { handleSavedSearch } from './handle_saved_search'; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/visualize_app_state.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/visualize_app_state.ts index d3fae3d457b63..86f39ea76dd3a 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/visualize_app_state.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/visualize_app_state.ts @@ -17,7 +17,7 @@ * under the License. */ -import { isFunction, omit } from 'lodash'; +import { isFunction, omit, union } from 'lodash'; import { migrateAppState } from './migrate_app_state'; import { @@ -75,10 +75,10 @@ export function useVisualizeAppState({ stateDefaults, kbnUrlStateStorage }: Argu query: defaultQuery, }; }, - unlinkSavedSearch: state => (query, filters) => ({ + unlinkSavedSearch: state => ({ query, parentFilters = [] }) => ({ ...state, - query, - filters, + query: query || state.query, + filters: union(state.filters, parentFilters), linked: false, }), updateVisState: state => newVisState => ({ ...state, vis: toObject(newVisState) }), diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts index 55fccd75361a0..ccb3b3ddbb1da 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/types.d.ts @@ -52,7 +52,7 @@ export interface VisualizeAppStateTransitions { removeSavedQuery: (state: VisualizeAppState) => (defaultQuery: Query) => VisualizeAppState; unlinkSavedSearch: ( state: VisualizeAppState - ) => (query: Query, filters: Filter[]) => VisualizeAppState; + ) => ({ query, parentFilters }: { query?: Query; parentFilters?: Filter[] }) => VisualizeAppState; updateVisState: (state: VisualizeAppState) => (vis: PureVisState) => VisualizeAppState; updateFromSavedQuery: (state: VisualizeAppState) => (savedQuery: SavedQuery) => VisualizeAppState; } diff --git a/src/plugins/kibana_utils/public/state_management/url/index.ts b/src/plugins/kibana_utils/public/state_management/url/index.ts index e28d183c6560a..6fbf2a009f7a3 100644 --- a/src/plugins/kibana_utils/public/state_management/url/index.ts +++ b/src/plugins/kibana_utils/public/state_management/url/index.ts @@ -23,6 +23,7 @@ export { setStateToKbnUrl, getStateFromKbnUrl, getStatesFromKbnUrl, + removeStateFromKbnUrl, IKbnUrlControls, } from './kbn_url_storage'; export { createKbnUrlTracker } from './kbn_url_tracker'; diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts index 40a411d425a54..ac8a970937619 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts @@ -96,6 +96,13 @@ export function setStateToKbnUrl( }); } +/** + * Removes passed key from the url and returns a new url string. + */ +export function removeStateFromKbnUrl(key: string, rawUrl = window.location.href): string { + return replaceUrlHashQuery(rawUrl, ({ [key]: value, ...query }) => query); +} + /** * A tiny wrapper around history library to listen for url changes and update url * History library handles a bunch of cross browser edge cases diff --git a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts index 082eaa5095ab9..8e75ba38db944 100644 --- a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts +++ b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts @@ -25,6 +25,7 @@ import { createKbnUrlControls, getStateFromKbnUrl, setStateToKbnUrl, + removeStateFromKbnUrl, } from '../../state_management/url'; export interface IKbnUrlStateStorage extends IStateStorage { @@ -34,6 +35,9 @@ export interface IKbnUrlStateStorage extends IStateStorage { opts?: { replace: boolean } ) => Promise; get: (key: string) => State | null; + + // removes the key from url + remove: (key: string) => Promise; change$: (key: string) => Observable; // cancels any pending url updates @@ -54,17 +58,14 @@ export const createKbnUrlStateStorage = ( ): IKbnUrlStateStorage => { const url = createKbnUrlControls(history); return { - set: ( - key: string, - state: State, - { replace = false }: { replace: boolean } = { replace: false } - ) => { + set: (key, state, { replace = false }: { replace: boolean } = { replace: false }) => { // syncState() utils doesn't wait for this promise return url.updateAsync( currentUrl => setStateToKbnUrl(key, state, { useHash }, currentUrl), replace ); }, + remove: key => url.updateAsync(currentUrl => removeStateFromKbnUrl(key, currentUrl)), get: key => { // if there is a pending url update, then state will be extracted from that pending url, // otherwise current url will be used to retrieve state from From bdc2e4a9de452f61c8cd883516b446e50f9eb39c Mon Sep 17 00:00:00 2001 From: sulemanof Date: Tue, 10 Mar 2020 12:34:23 +0300 Subject: [PATCH 2/4] Revert relying on savedSearchId in url --- .../visualize/np_ready/editor/editor.js | 58 +++++++++--- .../editor/lib/handle_saved_search.ts | 94 ------------------- .../visualize/np_ready/editor/lib/index.ts | 1 - .../public/state_management/url/index.ts | 1 - .../state_management/url/kbn_url_storage.ts | 7 -- .../create_kbn_url_state_storage.ts | 11 +-- 6 files changed, 50 insertions(+), 122 deletions(-) delete mode 100644 src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index 6a9b94c6556fc..e3d51911c2e58 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -25,7 +25,7 @@ import { i18n } from '@kbn/i18n'; import React from 'react'; import { FormattedMessage } from '@kbn/i18n/react'; -import { makeStateful, useVisualizeAppState, handleSavedSearch } from './lib'; +import { makeStateful, useVisualizeAppState } from './lib'; import { VisualizeConstants } from '../visualize_constants'; import { getEditBreadcrumbs } from '../breadcrumbs'; @@ -115,7 +115,8 @@ function VisualizeAppController( savedVis.vis.on('apply', _applyVis); // vis is instance of src/legacy/ui/public/vis/vis.js. // SearchSource is a promise-based stream of search results that can inherit from other search sources. - const { vis, searchSource } = savedVis; + const { vis, searchSource, savedSearchId } = savedVis; + const searchSourceParent = searchSource.getParent(); $scope.vis = vis; @@ -379,6 +380,18 @@ function VisualizeAppController( }, }; + const handleLinkedSearch = linked => { + if (linked && !savedVis.savedSearchId) { + savedVis.savedSearchId = savedSearchId; + vis.savedSearchId = savedSearchId; + + searchSource.setParent(searchSourceParent); + } else if (!linked && savedVis.savedSearchId) { + delete savedVis.savedSearchId; + delete vis.savedSearchId; + } + }; + // Create a PersistedState instance for uiState. const { persistedState, unsubscribePersisted, persistOnChange } = makeStateful( 'uiState', @@ -387,9 +400,9 @@ function VisualizeAppController( $scope.uiState = persistedState; $scope.savedVis = savedVis; $scope.query = initialState.query; - $scope.linked = initialState.linked; $scope.searchSource = searchSource; $scope.refreshInterval = timefilter.getRefreshInterval(); + handleLinkedSearch(initialState.linked); const addToDashMode = $route.current.params[DashboardConstants.ADD_VISUALIZATION_TO_DASHBOARD_MODE_PARAM]; @@ -468,7 +481,7 @@ function VisualizeAppController( $scope.fetch = function() { const { query, linked, filters } = stateContainer.getState(); $scope.query = query; - $scope.linked = linked; + handleLinkedSearch(linked); savedVis.searchSource.setField('query', query); savedVis.searchSource.setField('filter', filters); $scope.$broadcast('render'); @@ -488,15 +501,6 @@ function VisualizeAppController( }) ); - // handle linked search updates, such as link/unlink a saved search - handleSavedSearch({ - kbnUrlStateStorage, - savedVis, - stateContainer, - toastNotifications, - vis, - }); - $scope.$on('$destroy', () => { if ($scope._handler) { $scope._handler.destroy(); @@ -657,6 +661,32 @@ function VisualizeAppController( ); } + const unlinkFromSavedSearch = () => { + if (!searchSourceParent) { + return; + } + + const searchSourceGrandparent = searchSourceParent.getParent(); + const currentIndex = searchSourceParent.getField('index'); + + searchSource.setField('index', currentIndex); + searchSource.setParent(searchSourceGrandparent); + + stateContainer.transitions.unlinkSavedSearch({ + query: searchSourceParent.getField('query'), + parentFilters: searchSourceParent.getOwnField('filter'), + }); + + toastNotifications.addSuccess( + i18n.translate('kbn.visualize.linkedToSearch.unlinkSuccessNotificationText', { + defaultMessage: `Unlinked from saved search '{searchTitle}'`, + values: { + searchTitle: savedVis.savedSearch.title, + }, + }) + ); + }; + $scope.getAdditionalMessage = () => { return ( '' + @@ -668,6 +698,8 @@ function VisualizeAppController( ); }; + vis.on('unlinkFromSavedSearch', unlinkFromSavedSearch); + addHelpMenuToAppChrome(chrome, docLinks); init(); diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts deleted file mode 100644 index cb892d278daed..0000000000000 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/handle_saved_search.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Licensed to Elasticsearch B.V. under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch B.V. licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -import { i18n } from '@kbn/i18n'; - -import { ToastsStart } from 'kibana/public'; -import { Vis, VisSavedObject } from 'src/legacy/core_plugins/visualizations/public'; -import { Filter } from 'src/plugins/data/public'; -import { - IKbnUrlStateStorage, - ReduxLikeStateContainer, -} from '../../../../../../../../plugins/kibana_utils/public'; -import { VisualizeAppStateTransitions, VisualizeAppState } from '../../types'; - -interface Arguments { - kbnUrlStateStorage: IKbnUrlStateStorage; - savedVis: VisSavedObject; - stateContainer: ReduxLikeStateContainer; - toastNotifications: ToastsStart; - vis: Vis; -} - -/** - * Handles changes around linked search to a saved object - */ -export const handleSavedSearch = ({ - kbnUrlStateStorage, - savedVis, - stateContainer, - toastNotifications, - vis, -}: Arguments) => { - const { searchSource } = savedVis; - const searchSourceParent = searchSource.getParent(); - const searchSourceGrandparent = searchSourceParent?.getParent(); - - kbnUrlStateStorage.change$('savedSearchId').subscribe(savedSearchId => { - if (savedSearchId && !savedVis.savedSearchId) { - savedVis.savedSearchId = savedSearchId; - vis.savedSearchId = savedSearchId; - - searchSource.setParent(searchSourceParent); - } else if (!savedSearchId && savedVis.savedSearchId) { - delete savedVis.savedSearchId; - delete vis.savedSearchId; - } - }); - - const unlinkFromSavedSearch = () => { - if (!searchSourceParent) { - return; - } - - const currentIndex = searchSourceParent.getField('index'); - - kbnUrlStateStorage.remove('savedSearchId'); - kbnUrlStateStorage.set('indexPattern', currentIndex?.id); - - searchSource.setField('index', currentIndex); - searchSource.setParent(searchSourceGrandparent); - - stateContainer.transitions.unlinkSavedSearch({ - query: searchSourceParent.getField('query'), - parentFilters: searchSourceParent.getOwnField('filter') as Filter[], - }); - - toastNotifications.addSuccess( - i18n.translate('kbn.visualize.linkedToSearch.unlinkSuccessNotificationText', { - defaultMessage: `Unlinked from saved search '{searchTitle}'`, - values: { - searchTitle: savedVis.savedSearch?.title, - }, - }) - ); - }; - - vis.on('unlinkFromSavedSearch', unlinkFromSavedSearch); -}; diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts index c7aad0286308b..fa5b91b00edaf 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/lib/index.ts @@ -19,4 +19,3 @@ export { useVisualizeAppState } from './visualize_app_state'; export { makeStateful } from './make_stateful'; -export { handleSavedSearch } from './handle_saved_search'; diff --git a/src/plugins/kibana_utils/public/state_management/url/index.ts b/src/plugins/kibana_utils/public/state_management/url/index.ts index 6fbf2a009f7a3..e28d183c6560a 100644 --- a/src/plugins/kibana_utils/public/state_management/url/index.ts +++ b/src/plugins/kibana_utils/public/state_management/url/index.ts @@ -23,7 +23,6 @@ export { setStateToKbnUrl, getStateFromKbnUrl, getStatesFromKbnUrl, - removeStateFromKbnUrl, IKbnUrlControls, } from './kbn_url_storage'; export { createKbnUrlTracker } from './kbn_url_tracker'; diff --git a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts index ac8a970937619..40a411d425a54 100644 --- a/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts +++ b/src/plugins/kibana_utils/public/state_management/url/kbn_url_storage.ts @@ -96,13 +96,6 @@ export function setStateToKbnUrl( }); } -/** - * Removes passed key from the url and returns a new url string. - */ -export function removeStateFromKbnUrl(key: string, rawUrl = window.location.href): string { - return replaceUrlHashQuery(rawUrl, ({ [key]: value, ...query }) => query); -} - /** * A tiny wrapper around history library to listen for url changes and update url * History library handles a bunch of cross browser edge cases diff --git a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts index 8e75ba38db944..082eaa5095ab9 100644 --- a/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts +++ b/src/plugins/kibana_utils/public/state_sync/state_sync_state_storage/create_kbn_url_state_storage.ts @@ -25,7 +25,6 @@ import { createKbnUrlControls, getStateFromKbnUrl, setStateToKbnUrl, - removeStateFromKbnUrl, } from '../../state_management/url'; export interface IKbnUrlStateStorage extends IStateStorage { @@ -35,9 +34,6 @@ export interface IKbnUrlStateStorage extends IStateStorage { opts?: { replace: boolean } ) => Promise; get: (key: string) => State | null; - - // removes the key from url - remove: (key: string) => Promise; change$: (key: string) => Observable; // cancels any pending url updates @@ -58,14 +54,17 @@ export const createKbnUrlStateStorage = ( ): IKbnUrlStateStorage => { const url = createKbnUrlControls(history); return { - set: (key, state, { replace = false }: { replace: boolean } = { replace: false }) => { + set: ( + key: string, + state: State, + { replace = false }: { replace: boolean } = { replace: false } + ) => { // syncState() utils doesn't wait for this promise return url.updateAsync( currentUrl => setStateToKbnUrl(key, state, { useHash }, currentUrl), replace ); }, - remove: key => url.updateAsync(currentUrl => removeStateFromKbnUrl(key, currentUrl)), get: key => { // if there is a pending url update, then state will be extracted from that pending url, // otherwise current url will be used to retrieve state from From 85e40c028e29c3c3600a1303896f79f59307b1f6 Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 11 Mar 2020 14:41:41 +0300 Subject: [PATCH 3/4] Fix comments --- .../visualize/np_ready/editor/editor.js | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index e3d51911c2e58..5a7bd0883508b 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -115,8 +115,7 @@ function VisualizeAppController( savedVis.vis.on('apply', _applyVis); // vis is instance of src/legacy/ui/public/vis/vis.js. // SearchSource is a promise-based stream of search results that can inherit from other search sources. - const { vis, searchSource, savedSearchId } = savedVis; - const searchSourceParent = searchSource.getParent(); + const { vis, searchSource, savedSearch } = savedVis; $scope.vis = vis; @@ -381,14 +380,11 @@ function VisualizeAppController( }; const handleLinkedSearch = linked => { - if (linked && !savedVis.savedSearchId) { - savedVis.savedSearchId = savedSearchId; - vis.savedSearchId = savedSearchId; - - searchSource.setParent(searchSourceParent); + if (linked && !savedVis.savedSearchId && savedSearch) { + savedVis.savedSearchId = savedSearch.id; + searchSource.setParent(savedSearch.searchSource); } else if (!linked && savedVis.savedSearchId) { delete savedVis.savedSearchId; - delete vis.savedSearchId; } }; @@ -662,10 +658,7 @@ function VisualizeAppController( } const unlinkFromSavedSearch = () => { - if (!searchSourceParent) { - return; - } - + const searchSourceParent = savedSearch.searchSource; const searchSourceGrandparent = searchSourceParent.getParent(); const currentIndex = searchSourceParent.getField('index'); @@ -681,7 +674,7 @@ function VisualizeAppController( i18n.translate('kbn.visualize.linkedToSearch.unlinkSuccessNotificationText', { defaultMessage: `Unlinked from saved search '{searchTitle}'`, values: { - searchTitle: savedVis.savedSearch.title, + searchTitle: savedSearch.title, }, }) ); From b45bd075bfd77c553fc3438a6f1e655cb989ed8a Mon Sep 17 00:00:00 2001 From: sulemanof Date: Wed, 11 Mar 2020 17:55:06 +0300 Subject: [PATCH 4/4] Return back savedSearchId into vis object --- .../kibana/public/visualize/np_ready/editor/editor.js | 2 ++ .../visualizations/public/np_ready/public/vis.ts | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js index 5a7bd0883508b..3fab650002c17 100644 --- a/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js +++ b/src/legacy/core_plugins/kibana/public/visualize/np_ready/editor/editor.js @@ -382,9 +382,11 @@ function VisualizeAppController( const handleLinkedSearch = linked => { if (linked && !savedVis.savedSearchId && savedSearch) { savedVis.savedSearchId = savedSearch.id; + vis.savedSearchId = savedSearch.id; searchSource.setParent(savedSearch.searchSource); } else if (!linked && savedVis.savedSearchId) { delete savedVis.savedSearchId; + delete vis.savedSearchId; } }; diff --git a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts index f658f6ef52df8..ba86125f2e246 100644 --- a/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts +++ b/src/legacy/core_plugins/visualizations/public/np_ready/public/vis.ts @@ -32,6 +32,12 @@ export interface Vis { aggs: Array<{ [key: string]: any }>; }; + /** + * If a visualization based on the saved search, + * the id is necessary for building an expression function in src/plugins/expressions/common/expression_functions/specs/kibana_context.ts + */ + savedSearchId?: string; + // Since we haven't typed everything here yet, we basically "any" the rest // of that interface. This should be removed as soon as this type definition // has been completed. But that way we at least have typing for a couple of