import React , { useEffect , useRef , useState } from 'react' ; import { History } from 'history' ; import { FormattedMessage , I18nProvider } from '@osd/i18n/react' ; import { Router } from 'react-router-dom' ; import { EuiFieldText , EuiPage , EuiPageBody , EuiPageContent , EuiPageHeader , EuiTitle , } from '@elastic/eui' ; import { CoreStart } from '../../../../../src/core/public' ; import { NavigationPublicPluginStart } from '../../../../../src/plugins/navigation/public' ; import { connectToQueryState , syncQueryStateWithUrl , DataPublicPluginStart , IIndexPattern , QueryState , Filter , opensearchFilters , Query , } from '../../../../../src/plugins/data/public' ; import { BaseState , BaseStateContainer , createStateContainer , createStateContainerReactHelpers , IOsdUrlStateStorage , ReduxLikeStateContainer , syncState , } from '../../../../../src/plugins/opensearch_dashboards_utils/public' ; import { PLUGIN_ID , PLUGIN_NAME } from '../../../common' ; interface StateDemoAppDeps { notifications : CoreStart [ 'notifications' ] ; http : CoreStart [ 'http' ] ; navigation : NavigationPublicPluginStart ; data : DataPublicPluginStart ; history : History ; osdUrlStateStorage : IOsdUrlStateStorage ; } interface AppState { name : string ; filters : Filter [ ] ; query ? : Query ; } const defaultAppState = { name : '' , filters : [ ] , } ; const { Provider : AppStateContainerProvider , useState : useAppState , useContainer : useAppStateContainer , } = createStateContainerReactHelpers < ReduxLikeStateContainer < AppState > > ( ) ; const App = ( { navigation , data , history , osdUrlStateStorage } ) => { const appStateContainer = useAppStateContainer ( ) ; const appState = useAppState ( ) ; useGlobalStateSyncing ( data . query , osdUrlStateStorage ) ; useAppStateSyncing ( appStateContainer , data . query , osdUrlStateStorage ) ; const indexPattern = useIndexPattern ( data ) ; if ( ! indexPattern ) return < div > No index pattern found . Please create an index patter before loading ... < /div>; return ( < Router history = { history } > < I18nProvider > < > < navigation . ui . TopNavMenu appName = { PLUGIN_ID } showSearchBar = { true } indexPatterns = { [ indexPattern ] } useDefaultBehaviors = { true } showSaveQuery = { true } / > < EuiPage restrictWidth = "1000px" > < EuiPageBody > < EuiPageHeader > < EuiTitle size = "l" > < h1 > < FormattedMessage id = "stateDemo.helloWorldText" defaultMessage = "{name}!" values = { { name : PLUGIN_NAME } } /> < /h1> < /EuiTitle> < /EuiPageHeader> < EuiPageContent > < EuiFieldText placeholder = "Additional application state: My name is..." value = { appState . name } onChange = { ( e ) => appStateContainer . set ( { ... appState , name : e . target . value } ) } aria - label = "My name" / > < /EuiPageContent> < /EuiPageBody> < /EuiPage> < /> < /I18nProvider> < /Router>); } ; export const StateDemoApp = ( props ) => { const appStateContainer = useCreateStateContainer ( defaultAppState ) ; return ( < AppStateContainerProvider value = { appStateContainer } > < App { ... props } / > < /AppStateContainerProvider>); } ; function useCreateStateContainer < State extends BaseState > ( defaultState ) { const stateContainerRef = useRef < ReduxLikeStateContainer < State > | null > ( null ) ; if ( ! stateContainerRef . current ) { stateContainerRef . current = createStateContainer ( defaultState ) ; } return stateContainerRef . current ; } function useIndexPattern ( data ) { const [ indexPattern , setIndexPattern ] = useState < IIndexPattern > ( ) ; useEffect ( ( ) => { const fetchIndexPattern = async ( ) => { const defaultIndexPattern = await data . indexPatterns . getDefault ( ) ; if ( defaultIndexPattern ) { setIndexPattern ( defaultIndexPattern ) ; } } ; fetchIndexPattern ( ) ; } , [ data . indexPatterns ] ) ; return indexPattern ; } function useGlobalStateSyncing ( query , osdUrlStateStorage ) { useEffect ( ( ) => { const { stop } = syncQueryStateWithUrl ( query , osdUrlStateStorage ) ; return ( ) => { stop ( ) ; } ; } , [ query , osdUrlStateStorage ] ) ; } function useAppStateSyncing < AppState extends QueryState > ( appStateContainer , query , osdUrlStateStorage ) { useEffect ( ( ) => { const stopSyncingQueryAppStateWithStateContainer = connectToQueryState ( query , appStateContainer , { filters : opensearchFilters . FilterStateStore . APP_STATE , query : true } ) ; const { start : startSyncingAppStateWithUrl , stop : stopSyncingAppStateWithUrl } = syncState ( { storageKey : '_a' , stateStorage : osdUrlStateStorage , stateContainer : { ... appStateContainer , set : ( state ) => state && appStateContainer . set ( state ) , } , } ) ; const initialAppState = { ... appStateContainer . get ( ) , ... osdUrlStateStorage . get < AppState > ( '_a' ) , } ; appStateContainer . set ( initialAppState ) ; osdUrlStateStorage . set < AppState > ( '_a' , initialAppState ) ; startSyncingAppStateWithUrl ( ) ; return ( ) => { stopSyncingQueryAppStateWithStateContainer ( ) ; stopSyncingAppStateWithUrl ( ) ; } ; } , [ query , osdUrlStateStorage , appStateContainer ] ) ; }