From 00e950c2d4ca8b5551101cc1a175226ada97eb2c Mon Sep 17 00:00:00 2001 From: Daniil Suleiman <31325372+sulemanof@users.noreply.github.com> Date: Thu, 12 Mar 2020 12:08:48 +0300 Subject: [PATCH] [Visualize] Fix linked search behavior (#59690) * Fix linked search behavior * Revert relying on savedSearchId in url * Fix comments * Return back savedSearchId into vis object Co-authored-by: Elastic Machine --- .../visualize/np_ready/editor/editor.js | 56 ++++++++----------- .../editor/lib/visualize_app_state.ts | 8 +-- .../public/visualize/np_ready/types.d.ts | 2 +- .../public/np_ready/public/vis.ts | 6 ++ 4 files changed, 34 insertions(+), 38 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 e1a20e3381331..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 @@ -115,7 +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 } = savedVis; + const { vis, searchSource, savedSearch } = savedVis; $scope.vis = vis; @@ -379,6 +379,17 @@ 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; + } + }; + // Create a PersistedState instance for uiState. const { persistedState, unsubscribePersisted, persistOnChange } = makeStateful( 'uiState', @@ -387,9 +398,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 +479,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'); @@ -558,20 +569,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. */ @@ -663,33 +660,26 @@ function VisualizeAppController( } const unlinkFromSavedSearch = () => { - const searchSourceParent = searchSource.getParent(); + const searchSourceParent = savedSearch.searchSource; const searchSourceGrandparent = searchSourceParent.getParent(); + const currentIndex = searchSourceParent.getField('index'); - 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.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, + searchTitle: savedSearch.title, }, }) ); - - $scope.fetch(); }; $scope.getAdditionalMessage = () => { 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/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