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

[State Management] - Remove GlobalState from dashboard #55158

Merged
Merged
Show file tree
Hide file tree
Changes from 3 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 @@ -21,13 +21,7 @@ import _ from 'lodash';
import { Subscription } from 'rxjs';
import { State } from 'ui/state_management/state';
import { FilterManager, esFilters } from '../../../../../../plugins/data/public';

import {
compareFilters,
COMPARE_ALL_OPTIONS,
// this whole file will soon be deprecated by new state management.
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
} from '../../../../../../plugins/data/public/query/filter_manager/lib/compare_filters';
import { compareFilters, COMPARE_ALL_OPTIONS } from '../../../../../../plugins/data/public';

type GetAppStateFunc = () => { filters?: esFilters.Filter[]; save?: () => void } | undefined | null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
import chrome from 'ui/chrome';

export const legacyChrome = chrome;
export { State } from 'ui/state_management/state';
export { SavedObjectSaveOpts } from 'ui/saved_objects/types';
export { npSetup, npStart } from 'ui/new_platform';
export { IPrivate } from 'ui/private';
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,37 +19,39 @@

import { EuiConfirmModal, EuiIcon } from '@elastic/eui';
import angular, { IModule } from 'angular';
import { History } from 'history';
import { i18nDirective, i18nFilter, I18nProvider } from '@kbn/i18n/angular';
import {
AppMountContext,
ChromeStart,
IUiSettingsClient,
LegacyCoreStart,
SavedObjectsClientContract,
IUiSettingsClient,
} from 'kibana/public';
import { Storage } from '../../../../../../plugins/kibana_utils/public';
import { IKbnUrlStateStorage, Storage } from '../../../../../../plugins/kibana_utils/public';
import {
GlobalStateProvider,
StateManagementConfigProvider,
PrivateProvider,
EventsProvider,
PersistedState,
configureAppAngularModule,
confirmModalFactory,
createTopNavDirective,
createTopNavHelper,
PromiseServiceCreator,
EventsProvider,
IPrivate,
KbnUrlProvider,
PersistedState,
PrivateProvider,
PromiseServiceCreator,
RedirectWhenMissingProvider,
confirmModalFactory,
configureAppAngularModule,
SavedObjectLoader,
IPrivate,
StateManagementConfigProvider,
} from '../legacy_imports';

// @ts-ignore
import { initDashboardApp } from './legacy_app';
import { IEmbeddableStart } from '../../../../../../plugins/embeddable/public';
import { NavigationPublicPluginStart as NavigationStart } from '../../../../../../plugins/navigation/public';
import { DataPublicPluginStart as NpDataStart } from '../../../../../../plugins/data/public';
import {
DataPublicPluginStart as NpDataStart,
syncFilters,
} from '../../../../../../plugins/data/public';
import { SharePluginStart } from '../../../../../../plugins/share/public';

export interface RenderDeps {
Expand All @@ -67,21 +69,46 @@ export interface RenderDeps {
embeddables: IEmbeddableStart;
localStorage: Storage;
share: SharePluginStart;
kbnUrlStateStorage: IKbnUrlStateStorage;
history: History;

// hack: keeping the value nested
// as configureAppAngularModule() is called once and initialised with reference to 'hasInheritedGlobalState' ,
// so to be able to update underlying value, so angular controller could pick it up
// this param is used to determine if time filter saved with dashboard should be applied or not
hasInheritedGlobalState?: {
value: boolean;
};
}

let angularModuleInstance: IModule | null = null;
const hasInheritedGlobalStateRef: { value: boolean } = { value: false };

export const renderApp = (element: HTMLElement, appBasePath: string, deps: RenderDeps) => {
const { stop: stopSyncingGlobalFilters, hasInheritedFiltersFromUrl } = syncFilters(
deps.kbnUrlStateStorage,
deps.npDataStart.query.filterManager,
deps.npDataStart.query.timefilter.timefilter
);

// hack: always keeping the latest 'hasInheritedGlobalState' value in the same object - hasInheritedGlobalStateRef
// this is needed so angular Controller picks up the latest value, as it has reference to the hasInheritedGlobalStateRef
hasInheritedGlobalStateRef.value = hasInheritedFiltersFromUrl;
deps.hasInheritedGlobalState = hasInheritedGlobalStateRef;

if (!angularModuleInstance) {
angularModuleInstance = createLocalAngularModule(deps.core, deps.navigation);
// global routing stuff
configureAppAngularModule(angularModuleInstance, deps.core as LegacyCoreStart, true);
// custom routing stuff
initDashboardApp(angularModuleInstance, deps);
}

const $injector = mountDashboardApp(appBasePath, element);

return () => {
$injector.get('$rootScope').$destroy();
stopSyncingGlobalFilters();
};
};

Expand Down Expand Up @@ -146,17 +173,13 @@ function createLocalConfirmModalModule() {
}

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

function createLocalPersistedStateModule() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,14 +96,12 @@ export function initDashboardAppDirective(app: any, deps: RenderDeps) {
$route: any,
$routeParams: {
id?: string;
},
globalState: any
}
) =>
new DashboardAppController({
$route,
$scope,
$routeParams,
globalState,
config,
confirmModal,
indexPatterns: deps.npDataStart.indexPatterns,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import React from 'react';
import angular from 'angular';

import { Subscription } from 'rxjs';
import { createHashHistory } from 'history';
import { DashboardEmptyScreen, DashboardEmptyScreenProps } from './dashboard_empty_screen';

import {
Expand All @@ -32,12 +31,9 @@ import {
SavedObjectSaveOpts,
SaveResult,
showSaveModal,
State,
subscribeWithScope,
} from '../legacy_imports';
import { FilterStateManager } from '../../../../data/public';
import {
esFilters,
IndexPattern,
IndexPatternsContract,
Query,
Expand Down Expand Up @@ -77,12 +73,13 @@ import {
SavedObjectFinderUi,
} from '../../../../../../plugins/kibana_react/public';
import { removeQueryParam, unhashUrl } from '../../../../../../plugins/kibana_utils/public';
import { COMPARE_ALL_OPTIONS, compareFilters } from '../../../../../../plugins/data/public';
import { startSyncingAppFilters } from './lib/sync_app_filters';

export interface DashboardAppControllerDependencies extends RenderDeps {
$scope: DashboardAppScope;
$route: any;
$routeParams: any;
globalState: State;
indexPatterns: IndexPatternsContract;
dashboardConfig: any;
config: any;
Expand All @@ -99,7 +96,6 @@ export class DashboardAppController {
$scope,
$route,
$routeParams,
globalState,
dashboardConfig,
localStorage,
indexPatterns,
Expand All @@ -116,6 +112,9 @@ export class DashboardAppController {
},
},
core: { notifications, overlays, chrome, injectedMetadata, uiSettings, savedObjects, http },
history,
kbnUrlStateStorage,
hasInheritedGlobalState,
}: DashboardAppControllerDependencies) {
const queryFilter = filterManager;

Expand All @@ -126,34 +125,19 @@ export class DashboardAppController {
chrome.docTitle.change(dash.title);
}

const history = createHashHistory();
const dashboardStateManager = new DashboardStateManager({
savedDashboard: dash,
useHashedUrl: config.get('state:storeInSessionStorage'),
hideWriteControls: dashboardConfig.getHideWriteControls(),
kibanaVersion: injectedMetadata.getKibanaVersion(),
kbnUrlStateStorage,
history,
});

const filterStateManager = new FilterStateManager(
globalState,
() => {
// Temporary AppState replacement
return {
set filters(_filters: esFilters.Filter[]) {
dashboardStateManager.setFilters(_filters);
},
get filters() {
return dashboardStateManager.appState.filters;
},
};
},
filterManager
);
const stopSyncingAppFilters = startSyncingAppFilters(filterManager, dashboardStateManager);

// The hash check is so we only update the time filter on dashboard open, not during
// normal cross app navigation.
if (dashboardStateManager.getIsTimeSavedWithDashboard() && !globalState.$inheritedGlobalState) {
if (dashboardStateManager.getIsTimeSavedWithDashboard() && !hasInheritedGlobalState?.value) {
dashboardStateManager.syncTimefilterWithDashboard(timefilter);
}
$scope.showSaveQuery = dashboardCapabilities.saveQuery as boolean;
Expand Down Expand Up @@ -411,7 +395,15 @@ export class DashboardAppController {

const containerInput = dashboardContainer.getInput();
const differences: Partial<DashboardContainerInput> = {};
Object.keys(containerInput).forEach(key => {

// Filters shouldn't be compared using regular isEqual
if (
!compareFilters(containerInput.filters, appStateDashboardInput.filters, COMPARE_ALL_OPTIONS)
) {
differences.filters = appStateDashboardInput.filters;
}

Object.keys(_.omit(containerInput, 'filters')).forEach(key => {
const containerValue = (containerInput as { [key: string]: unknown })[key];
const appStateValue = ((appStateDashboardInput as unknown) as { [key: string]: unknown })[
key
Expand Down Expand Up @@ -878,6 +870,7 @@ export class DashboardAppController {

$scope.$on('$destroy', () => {
updateSubscription.unsubscribe();
stopSyncingAppFilters();
visibleSubscription.unsubscribe();
$scope.timefilterSubscriptions$.unsubscribe();

Expand All @@ -891,9 +884,6 @@ export class DashboardAppController {
if (dashboardContainer) {
dashboardContainer.destroy();
}
if (filterStateManager) {
filterStateManager.destroy();
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import { DashboardStateManager } from './dashboard_state_manager';
import { getSavedDashboardMock } from '../__tests__';
import { InputTimeRange, TimefilterContract, TimeRange } from 'src/plugins/data/public';
import { ViewMode } from 'src/plugins/embeddable/public';
import { createKbnUrlStateStorage } from 'src/plugins/kibana_utils/public';

jest.mock('ui/agg_types', () => ({
aggTypes: {
Expand All @@ -48,9 +49,9 @@ describe('DashboardState', function() {
function initDashboardState() {
dashboardState = new DashboardStateManager({
savedDashboard,
useHashedUrl: false,
hideWriteControls: false,
kibanaVersion: '7.0.0',
kbnUrlStateStorage: createKbnUrlStateStorage(),
history: createBrowserHistory(),
});
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@

import { i18n } from '@kbn/i18n';
import _ from 'lodash';
import { History } from 'history';
import { Subscription } from 'rxjs';
import { Moment } from 'moment';
import { History } from 'history';

import { DashboardContainer } from 'src/legacy/core_plugins/dashboard_embeddable_container/public/np_ready/public';
import { ViewMode } from '../../../../../../plugins/embeddable/public';
Expand All @@ -44,7 +44,6 @@ import {
SavedDashboardPanel,
} from './types';
import {
createKbnUrlStateStorage,
createStateContainer,
IKbnUrlStateStorage,
ISyncStateRef,
Expand Down Expand Up @@ -97,13 +96,13 @@ export class DashboardStateManager {
savedDashboard,
hideWriteControls,
kibanaVersion,
useHashedUrl,
kbnUrlStateStorage,
history,
}: {
savedDashboard: SavedObjectDashboard;
hideWriteControls: boolean;
kibanaVersion: string;
useHashedUrl: boolean;
kbnUrlStateStorage: IKbnUrlStateStorage;
history: History;
}) {
this.history = history;
Expand All @@ -117,7 +116,7 @@ export class DashboardStateManager {
kibanaVersion
);

this.kbnUrlStateStorage = createKbnUrlStateStorage({ useHash: useHashedUrl, history });
this.kbnUrlStateStorage = kbnUrlStateStorage;

// setup initial state by merging defaults with state from url
// also run migration, as state in url could be of older version
Expand Down
Loading