Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Visualize] Remove global state in visualize #58352

Merged
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,8 @@
* directly where they are needed.
*/

export { State } from 'ui/state_management/state';
// @ts-ignore
export { GlobalStateProvider } from 'ui/state_management/global_state';
// @ts-ignore
export { StateManagementConfigProvider } from 'ui/state_management/config_provider';

export { subscribeWithScope } from 'ui/utils/subscribe_with_scope';
// @ts-ignore
export { EventsProvider } from 'ui/events';
export { registerTimefilterWithGlobalStateFactory } from 'ui/timefilter/setup_router';
// @ts-ignore
export { KbnUrlProvider, RedirectWhenMissingProvider } from 'ui/url';
export { absoluteToParsedUrl } from 'ui/url/absolute_to_parsed_url';
export { KibanaParsedUrl } from 'ui/url/kibana_parsed_url';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,11 @@ import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
import { AppMountContext } from 'kibana/public';
import {
configureAppAngularModule,
GlobalStateProvider,
KbnUrlProvider,
RedirectWhenMissingProvider,
IPrivate,
PrivateProvider,
PromiseServiceCreator,
StateManagementConfigProvider,
} from '../legacy_imports';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public';
import {
Expand Down Expand Up @@ -87,55 +85,27 @@ function createLocalAngularModule(core: AppMountContext['core'], navigation: Nav
createLocalI18nModule();
createLocalPrivateModule();
createLocalPromiseModule();
createLocalConfigModule(core);
createLocalKbnUrlModule();
createLocalStateModule();
createLocalTopNavModule(navigation);

const visualizeAngularModule: IModule = angular.module(moduleName, [
...thirdPartyAngularDependencies,
'app/visualize/Config',
'app/visualize/I18n',
'app/visualize/Private',
'app/visualize/TopNav',
'app/visualize/State',
'app/visualize/KbnUrl',
'app/visualize/Promise',
]);
return visualizeAngularModule;
}

function createLocalStateModule() {
angular
.module('app/visualize/State', [
'app/visualize/Private',
'app/visualize/Config',
'app/visualize/KbnUrl',
'app/visualize/Promise',
])
.service('globalState', function(Private: IPrivate) {
return Private(GlobalStateProvider);
});
}

function createLocalKbnUrlModule() {
angular
.module('app/visualize/KbnUrl', ['app/visualize/Private', 'ngRoute'])
.service('kbnUrl', (Private: IPrivate) => Private(KbnUrlProvider))
.service('redirectWhenMissing', (Private: IPrivate) => Private(RedirectWhenMissingProvider));
}

function createLocalConfigModule(core: AppMountContext['core']) {
angular
.module('app/visualize/Config', ['app/visualize/Private'])
.provider('stateManagementConfig', StateManagementConfigProvider)
.provider('config', () => {
return {
$get: () => ({
get: core.uiSettings.get.bind(core.uiSettings),
}),
};
});
}

function createLocalPromiseModule() {
angular.module('app/visualize/Promise', []).service('Promise', PromiseServiceCreator);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@
refresh-interval="refreshInterval.value"
on-refresh-change="onRefreshChange"
show-save-query="showSaveQuery"
on-saved="onQuerySaved"
on-saved-query-updated="onSavedQueryUpdated"
on-saved="updateSavedQuery"
on-saved-query-updated="updateSavedQuery"
on-clear-saved-query="onClearSavedQuery"
>
</kbn-top-nav>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import angular from 'angular';
import _ from 'lodash';
import { Subscription } from 'rxjs';
import { map } from 'rxjs/operators';
import { i18n } from '@kbn/i18n';

import React from 'react';
Expand All @@ -29,13 +30,17 @@ import { VisualizeConstants } from '../visualize_constants';
import { getEditBreadcrumbs } from '../breadcrumbs';

import { addHelpMenuToAppChrome } from '../help_menu/help_menu_util';
import { FilterStateManager } from '../../../../../data/public';
import { unhashUrl } from '../../../../../../../plugins/kibana_utils/public';
import { kbnBaseUrl } from '../../../../../../../plugins/kibana_legacy/public';
import {
SavedObjectSaveModal,
showSaveModal,
} from '../../../../../../../plugins/saved_objects/public';
import {
esFilters,
connectToQueryState,
syncQueryStateWithUrl,
} from '../../../../../../../plugins/data/public';

import { initVisEditorDirective } from './visualization_editor';
import { initVisualizationDirective } from './visualization';
Expand Down Expand Up @@ -65,28 +70,21 @@ export function initEditorDirective(app, deps) {

function VisualizeAppController(
$scope,
$element,
$route,
$window,
$injector,
$timeout,
kbnUrl,
redirectWhenMissing,
Promise,
globalState,
config
kbnUrlStateStorage,
history
) {
const {
indexPatterns,
localStorage,
visualizeCapabilities,
share,
data: {
query: {
filterManager,
timefilter: { timefilter },
},
},
data: { query: queryService },
toastNotifications,
chrome,
getBasePath,
Expand All @@ -97,6 +95,17 @@ function VisualizeAppController(
setActiveUrl,
} = getServices();

const {
filterManager,
timefilter: { timefilter },
} = queryService;

// starts syncing `_g` portion of url with query services
const { stop: stopSyncingQueryServiceStateWithUrl } = syncQueryStateWithUrl(
queryService,
kbnUrlStateStorage
);

// Retrieve the resolved SavedVis instance.
const savedVis = $route.current.locals.savedVis;
const _applyVis = () => {
Expand Down Expand Up @@ -284,26 +293,24 @@ function VisualizeAppController(
linked: !!savedVis.savedSearchId,
};

const useHash = config.get('state:storeInSessionStorage');
const { stateContainer, stopStateSync } = useVisualizeAppState({
useHash,
stateDefaults,
kbnUrlStateStorage,
});

const filterStateManager = new FilterStateManager(
globalState,
() => {
// Temporary AppState replacement
return {
set filters(_filters) {
stateContainer.transitions.set('filters', _filters);
},
get filters() {
return stateContainer.getState().filters;
},
};
// sync initial app filters from state to filterManager
filterManager.setAppFilters(_.cloneDeep(stateContainer.getState().filters));
// setup syncing of app filters between appState and filterManager
const stopSyncingAppFilters = connectToQueryState(
queryService,
{
set: ({ filters }) => stateContainer.transitions.set('filters', filters),
get: () => ({ filters: stateContainer.getState().filters }),
state$: stateContainer.state$.pipe(map(state => ({ filters: state.filters }))),
},
filterManager
{
filters: esFilters.FilterStateStore.APP_STATE,
}
);

// The savedVis is pulled from elasticsearch, but the appState is pulled from the url, with the
Expand Down Expand Up @@ -335,6 +342,24 @@ function VisualizeAppController(
}
);

const updateSavedQueryFromUrl = savedQueryId => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This function is only setting savedQuery, but it's not triggering the updateFromSavedQuery transition (together with syncing the data plugin state) even though it looks like it should.

In 7.6 I can change the saved query in the url and it will re-apply the filters, but here it's just selecting it in the saved object management popover.

if (!savedQueryId) {
delete $scope.savedQuery;

return;
}

if ($scope.savedQuery && $scope.savedQuery.id === savedQueryId) {
return;
}

savedQueryService.getSavedQuery(savedQueryId).then(savedQuery => {
$scope.$evalAsync(() => {
$scope.updateSavedQuery(savedQuery);
});
});
};

function init() {
if (vis.indexPattern) {
$scope.indexPattern = vis.indexPattern;
Expand Down Expand Up @@ -388,14 +413,14 @@ function VisualizeAppController(
};

$scope.timeRange = timefilter.getTime();
$scope.opts = _.pick($scope, 'savedVis', 'isAddToDashMode');

const unsubscribeStateUpdates = stateContainer.subscribe(state => {
const newQuery = migrateLegacyQuery(state.query);
if (!_.isEqual(state.query, newQuery)) {
stateContainer.transitions.set('query', newQuery);
}
persistOnChange(state);
updateSavedQueryFromUrl(state.savedQuery);

// if the browser history was changed manually we need to reflect changes in the editor
if (!_.isEqual(vis.getState(), state.vis)) {
Expand All @@ -413,6 +438,9 @@ function VisualizeAppController(
$scope.$broadcast('render');
};

// update the query if savedQuery is stored
updateSavedQueryFromUrl(initialState.savedQuery);

const subscriptions = new Subscription();

subscriptions.add(
Expand All @@ -438,7 +466,7 @@ function VisualizeAppController(

// update the searchSource when query updates
$scope.fetch = function() {
const { query, filters, linked } = stateContainer.getState();
const { query, linked, filters } = stateContainer.getState();
$scope.query = query;
$scope.linked = linked;
savedVis.searchSource.setField('query', query);
Expand All @@ -451,7 +479,6 @@ function VisualizeAppController(
subscribeWithScope($scope, filterManager.getUpdates$(), {
next: () => {
$scope.filters = filterManager.getFilters();
$scope.globalFilters = filterManager.getGlobalFilters();
},
})
);
Expand All @@ -466,13 +493,14 @@ function VisualizeAppController(
$scope._handler.destroy();
}
savedVis.destroy();
filterStateManager.destroy();
subscriptions.unsubscribe();
$scope.vis.off('apply', _applyVis);

unsubscribePersisted();
unsubscribeStateUpdates();
stopStateSync();
stopSyncingQueryServiceStateWithUrl();
stopSyncingAppFilters();
});

$timeout(() => {
Expand Down Expand Up @@ -501,23 +529,14 @@ function VisualizeAppController(
});
};

$scope.onQuerySaved = savedQuery => {
$scope.savedQuery = savedQuery;
};

$scope.onSavedQueryUpdated = savedQuery => {
$scope.savedQuery = { ...savedQuery };
};

$scope.onClearSavedQuery = () => {
delete $scope.savedQuery;
stateContainer.transitions.removeSavedQuery(defaultQuery);
filterManager.setFilters(filterManager.getGlobalFilters());
$scope.fetch();
};

const updateStateFromSavedQuery = savedQuery => {
stateContainer.transitions.set('query', savedQuery.attributes.query);
stateContainer.transitions.updateFromSavedQuery(savedQuery);

const savedQueryFilters = savedQuery.attributes.filters || [];
const globalFilters = filterManager.getGlobalFilters();
Expand All @@ -532,25 +551,12 @@ function VisualizeAppController(
timefilter.setRefreshInterval(savedQuery.attributes.timefilter.refreshInterval);
}
}

$scope.fetch();
};

// update the query if savedQuery is stored
if (stateContainer.getState().savedQuery) {
savedQueryService.getSavedQuery(stateContainer.getState().savedQuery).then(savedQuery => {
$scope.$evalAsync(() => {
$scope.savedQuery = savedQuery;
});
});
}

$scope.$watch('savedQuery', newSavedQuery => {
if (!newSavedQuery) return;
stateContainer.transitions.set('savedQuery', newSavedQuery.id);

updateStateFromSavedQuery(newSavedQuery);
});
$scope.updateSavedQuery = savedQuery => {
$scope.savedQuery = savedQuery;
lizozom marked this conversation as resolved.
Show resolved Hide resolved
updateStateFromSavedQuery(savedQuery);
};

$scope.$watch('linked', linked => {
if (linked && !savedVis.savedSearchId) {
Expand Down Expand Up @@ -626,7 +632,10 @@ function VisualizeAppController(
savedVis.vis.title = savedVis.title;
savedVis.vis.description = savedVis.description;
} else {
kbnUrl.change(`${VisualizeConstants.EDIT_PATH}/{{id}}`, { id: savedVis.id });
history.replace({
...history.location,
pathname: `${VisualizeConstants.EDIT_PATH}/${savedVis.id}`,
});
}
}
});
Expand Down
Loading