diff --git a/plugins/main/public/components/common/search-bar/use-search-bar.ts b/plugins/main/public/components/common/search-bar/use-search-bar.ts index 02d823c501..0ac9e5c261 100644 --- a/plugins/main/public/components/common/search-bar/use-search-bar.ts +++ b/plugins/main/public/components/common/search-bar/use-search-bar.ts @@ -72,6 +72,7 @@ const useSearchBarConfiguration = ( const { query: queryService } = getDataPlugin(); const { savedQuery, setSavedQuery, clearSavedQuery } = useSavedQuery({ queryService, + setFilters, }); // states const [isLoading, setIsLoading] = useState(true); diff --git a/plugins/main/public/react-services/state-storage.ts b/plugins/main/public/react-services/state-storage.ts new file mode 100644 index 0000000000..7adb4adc1c --- /dev/null +++ b/plugins/main/public/react-services/state-storage.ts @@ -0,0 +1,127 @@ +import { IUiSettingsClient } from '../../../../src/core/public/ui_settings'; +import { + connectToQueryState, + DataPublicPluginStart, + opensearchFilters, + syncQueryStateWithUrl, +} from '../../../../src/plugins/data/public'; +import { History } from 'history'; +import { + createOsdUrlStateStorage, + createStateContainer, + IOsdUrlStateStorage, + syncState, +} from '../../../../src/plugins/opensearch_dashboards_utils/public'; +import { OSD_URL_STATE_STORAGE_ID } from '../../common/constants'; +import { AppState } from './app-state'; +import { migrateLegacyQuery } from '../utils/migrate_legacy_query'; +import { cloneDeep } from 'lodash'; +import { getDataPlugin, getUiSettings } from "../kibana-services"; +import NavigationService from "./navigation-service"; + +export default class OsdUrlStateStorage { + private static instance: OsdUrlStateStorage; + + public static getInstance() { + if (!this.instance) { + const data = getDataPlugin(); + const config = getUiSettings(); + const history = NavigationService.getInstance().getHistory(); + this.instance = new OsdUrlStateStorage(data, config, history); + } + return this.instance; + } + + private readonly osdUrlStateStorage: IOsdUrlStateStorage; + + public static readonly APP_STORAGE_KEY = '_a'; + + private constructor( + private readonly data: DataPublicPluginStart, + config: IUiSettingsClient, + history: History + ) { + this.osdUrlStateStorage = createOsdUrlStateStorage({ + useHash: config.get(OSD_URL_STATE_STORAGE_ID), + history: history, + }); + } + + get appStateFromUrl() { + return this.osdUrlStateStorage.get(OsdUrlStateStorage.APP_STORAGE_KEY) as AppState; + } + + get appStateContainer() { + const defaultQuery = migrateLegacyQuery(this.data.query.queryString.getDefaultQuery()); + let initialAppState = { + query: defaultQuery, + ...this.appStateFromUrl, + }; + return createStateContainer(initialAppState); + } + + public async replaceUrlAppState(newPartial: AppState = {}) { + const state = { ...this.appStateContainer.getState(), ...newPartial }; + await this.osdUrlStateStorage.set(OsdUrlStateStorage.APP_STORAGE_KEY, state, { replace: true }); + } + + public syncState() { + const { start, stop } = syncState({ + storageKey: OsdUrlStateStorage.APP_STORAGE_KEY, + stateContainer: this.appStateContainerModified(), + stateStorage: this.osdUrlStateStorage, + }); + + this.setAppFilters(); + this.setAppQuery(); + + const stopSyncingQueryAppStateWithStateContainer = this.connectToQueryState(); + const { stop: stopSyncingGlobalStateWithUrl } = this.syncQueryStateWithUrl(); + + this.replaceUrlAppState().then(() => start()); + + return { + stop: () => { + stop(); + stopSyncingGlobalStateWithUrl(); + stopSyncingQueryAppStateWithStateContainer(); + }, + }; + } + + private appStateContainerModified() { + return { + ...this.appStateContainer, + set: (value: AppState | null) => { + if (value) { + this.appStateContainer.set(value); + } + }, + }; + } + + private syncQueryStateWithUrl() { + return syncQueryStateWithUrl(this.data.query, this.osdUrlStateStorage); + } + + private connectToQueryState() { + return connectToQueryState(this.data.query, this.appStateContainer, { + filters: opensearchFilters.FilterStateStore.APP_STATE, + query: true, + }); + } + + private setAppFilters() { + // sync initial app filters from state to filterManager + // https://github.com/opensearch-project/OpenSearch-Dashboards/blob/2.13.0/src/plugins/dashboard/public/application/utils/use/use_dashboard_app_state.tsx#L84-L86 + this.data.query.filterManager.setAppFilters( + cloneDeep(this.appStateContainer.getState().filters) + ); + } + + private setAppQuery() { + this.data.query.queryString.setQuery( + migrateLegacyQuery(this.appStateContainer.getState().query) + ); + } +}