Skip to content

Commit

Permalink
chore: make environment adaptor globally available (#855)
Browse files Browse the repository at this point in the history
* make env adaptor globally available

- eliminates the need for the envAdaptor context
- Paves the way for envAdaptor usage in sagas

* move env adaptor registration into useEffect

ensures registration happens after mounting, during the initialization phase, and not on every rerender
  • Loading branch information
josephaxisa authored Oct 14, 2021
1 parent 474ee93 commit 9a9d9fe
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 93 deletions.
42 changes: 26 additions & 16 deletions packages/api-explorer/src/ApiExplorer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,15 +32,16 @@ import { Aside, ComponentsProvider, Layout, Page } from '@looker/components'
import type { SpecList } from '@looker/sdk-codegen'
import type { RunItSetter } from '@looker/run-it'
import { funFetch, fallbackFetch, OAuthScene } from '@looker/run-it'
import {
SearchContext,
LodeContext,
defaultLodeContextValue,
EnvAdaptorContext,
} from './context'
import { SearchContext, LodeContext, defaultLodeContextValue } from './context'
import type { IApixEnvAdaptor } from './utils'
import { EnvAdaptorConstants, getLoded, oAuthPath } from './utils'
import { Header, SideNav, ErrorBoundary } from './components'
import {
EnvAdaptorConstants,
getLoded,
oAuthPath,
registerEnvAdaptor,
unregisterEnvAdaptor,
} from './utils'
import { Header, SideNav, ErrorBoundary, Loader } from './components'
import {
specReducer,
initDefaultSpecState,
Expand Down Expand Up @@ -71,10 +72,10 @@ const ApiExplorer: FC<ApiExplorerProps> = ({
declarationsLodeUrl = `${apixFilesHost}/declarationsIndex.json`,
headless = false,
}) => {
const [initializing, setInitializing] = useState(true)
const location = useLocation()
const { setSdkLanguageAction } = useActions()
const oauthReturn = location.pathname === `/${oAuthPath}`

const [specState, specDispatch] = useReducer(
specReducer,
initDefaultSpecState(specs, location)
Expand All @@ -97,6 +98,13 @@ const ApiExplorer: FC<ApiExplorerProps> = ({
}
}, [])

useEffect(() => {
registerEnvAdaptor(envAdaptor)
setInitializing(false)

return () => unregisterEnvAdaptor()
}, [])

useEffect(() => {
if (headless) {
window.addEventListener('message', hasNavigationToggle)
Expand Down Expand Up @@ -144,16 +152,18 @@ const ApiExplorer: FC<ApiExplorerProps> = ({
initSdkLanguage()
}, [envAdaptor, setSdkLanguageAction])

const { loadGoogleFonts, themeCustomizations } = envAdaptor.themeOverrides()
const themeOverrides = envAdaptor.themeOverrides()

return (
<>
<ComponentsProvider
loadGoogleFonts={loadGoogleFonts}
themeCustomizations={themeCustomizations}
loadGoogleFonts={themeOverrides.loadGoogleFonts}
themeCustomizations={themeOverrides.themeCustomizations}
>
<ErrorBoundary logError={envAdaptor.logError.bind(envAdaptor)}>
<EnvAdaptorContext.Provider value={{ envAdaptor }}>
{initializing ? (
<Loader message="Initializing" themeOverrides={themeOverrides} />
) : (
<ErrorBoundary logError={envAdaptor.logError.bind(envAdaptor)}>
<LodeContext.Provider value={{ ...lode }}>
<SearchContext.Provider
value={{ searchSettings, setSearchSettings }}
Expand Down Expand Up @@ -193,8 +203,8 @@ const ApiExplorer: FC<ApiExplorerProps> = ({
</Page>
</SearchContext.Provider>
</LodeContext.Provider>
</EnvAdaptorContext.Provider>
</ErrorBoundary>
</ErrorBoundary>
)}
</ComponentsProvider>
{!headless && <BodyOverride />}
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ import type { FC } from 'react'
import React, { useContext } from 'react'
import { useHistory } from 'react-router-dom'
import { Markdown } from '@looker/code-editor'
import { EnvAdaptorContext, SearchContext } from '../../context'
import { SearchContext } from '../../context'
import { getEnvAdaptor } from '../../utils'
import { transformURL } from './utils'

interface DocMarkdownProps {
Expand All @@ -37,7 +38,6 @@ interface DocMarkdownProps {
}

export const DocMarkdown: FC<DocMarkdownProps> = ({ source, specKey }) => {
const { envAdaptor } = useContext(EnvAdaptorContext)
const {
searchSettings: { pattern },
} = useContext(SearchContext)
Expand All @@ -50,6 +50,7 @@ export const DocMarkdown: FC<DocMarkdownProps> = ({ source, specKey }) => {
} else if (url.startsWith(`/${specKey}`)) {
history.push(url)
} else if (url.startsWith('https://')) {
const envAdaptor = getEnvAdaptor()
envAdaptor.openBrowserWindow(url)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,24 +24,22 @@
*/
import type { FC } from 'react'
import React, { useContext } from 'react'
import React from 'react'
import { codeGenerators } from '@looker/sdk-codegen'
import { Select } from '@looker/components'
import { useSelector } from 'react-redux'
import type { SelectOptionProps } from '@looker/components'

import { useActions } from '../../hooks'
import { getSelectedSdkLanguage } from '../../state'
import { EnvAdaptorContext } from '../../context'
import { EnvAdaptorConstants } from '../../utils'
import { EnvAdaptorConstants, getEnvAdaptor } from '../../utils'

/**
* Allows the user to select their preferred SDK language
*/
export const SdkLanguageSelector: FC = () => {
const { setSdkLanguageAction } = useActions()
const selectedSdkLanguage = useSelector(getSelectedSdkLanguage)
const { envAdaptor } = useContext(EnvAdaptorContext)

const allSdkLanguages: SelectOptionProps[] = codeGenerators.map((gen) => ({
value: gen.language,
Expand All @@ -57,6 +55,7 @@ export const SdkLanguageSelector: FC = () => {

const handleChange = (language: string) => {
setSdkLanguageAction(language)
const envAdaptor = getEnvAdaptor()
envAdaptor.localStorageSetItem(
EnvAdaptorConstants.LOCALSTORAGE_SDK_LANGUAGE_KEY,
language
Expand Down
39 changes: 0 additions & 39 deletions packages/api-explorer/src/context/envAdaptor/EnvAdaptorContext.ts

This file was deleted.

1 change: 0 additions & 1 deletion packages/api-explorer/src/context/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,3 @@
*/
export { LodeContext, defaultLodeContextValue } from './lode'
export { SearchContext, defaultSearchContextValue } from './search'
export { EnvAdaptorContext, defaultEnvAdaptorContextValue } from './envAdaptor'
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@
SOFTWARE.
*/
export {
defaultEnvAdaptorContextValue,
EnvAdaptorContext,
} from './EnvAdaptorContext'
import type { IApixEnvAdaptor } from '../utils'
import { registerEnvAdaptor, StandaloneEnvAdaptor } from '../utils'

export const registerTestEnvAdaptor = (envAdaptor?: IApixEnvAdaptor) => {
registerEnvAdaptor(envAdaptor || new StandaloneEnvAdaptor())
}
1 change: 1 addition & 0 deletions packages/api-explorer/src/test-utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,4 @@ export {
renderWithReduxProvider,
withReduxProvider,
} from './redux'
export { registerTestEnvAdaptor } from './envAdaptor'
26 changes: 6 additions & 20 deletions packages/api-explorer/src/test-utils/redux.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,43 +32,29 @@ import type { RenderOptions } from '@testing-library/react'

import type { RootState } from '../state'
import { configureStore } from '../state'
import type { IApixEnvAdaptor } from '../utils'
import { StandaloneEnvAdaptor } from '../utils'
import { EnvAdaptorContext } from '../context'
import { registerEnvAdaptor, StandaloneEnvAdaptor } from '../utils'
import { renderWithRouter } from '.'

const defaultStore = configureStore()

export const withReduxProvider = (
consumers: ReactElement<any>,
store: Store<RootState> = defaultStore,
envAdaptor: IApixEnvAdaptor = new StandaloneEnvAdaptor()
store: Store<RootState> = defaultStore
) => {
return (
<Provider store={store}>
<EnvAdaptorContext.Provider value={{ envAdaptor }}>
{consumers}
</EnvAdaptorContext.Provider>
</Provider>
)
registerEnvAdaptor(new StandaloneEnvAdaptor())
return <Provider store={store}>{consumers}</Provider>
}

export const renderWithReduxProvider = (
consumers: ReactElement<any>,
store?: Store<RootState>,
envAdaptor?: IApixEnvAdaptor,
options?: Omit<RenderOptions, 'queries'>
) => renderWithTheme(withReduxProvider(consumers, store, envAdaptor), options)
) => renderWithTheme(withReduxProvider(consumers, store), options)

export const renderWithRouterAndReduxProvider = (
consumers: ReactElement<any>,
initialEntries: string[] = ['/'],
store?: Store<RootState>,
envAdaptor?: IApixEnvAdaptor,
options?: Omit<RenderOptions, 'queries'>
) =>
renderWithRouter(
withReduxProvider(consumers, store, envAdaptor),
initialEntries,
options
)
renderWithRouter(withReduxProvider(consumers, store), initialEntries, options)
8 changes: 1 addition & 7 deletions packages/api-explorer/src/test-utils/render_with_lode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@ import { renderWithTheme } from '@looker/components-test-utils'
import type { IDeclarationMine, IExampleMine } from '@looker/sdk-codegen'
import { LodeContext } from '../context'
import type { RootState } from '../state'
import type { IApixEnvAdaptor } from '../utils'
import { withReduxProvider } from './redux'

const withLode = (
Expand Down Expand Up @@ -62,14 +61,9 @@ export const renderWithReduxProviderAndLode = (
examples: IExampleMine,
declarations?: IDeclarationMine,
store?: Store<RootState>,
envAdaptor?: IApixEnvAdaptor,
options?: Omit<RenderOptions, 'queries'>
) =>
renderWithTheme(
withReduxProvider(
withLode(component, examples, declarations),
store,
envAdaptor
),
withReduxProvider(withLode(component, examples, declarations), store),
options
)
26 changes: 26 additions & 0 deletions packages/api-explorer/src/utils/envAdaptor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,29 @@ export class StandaloneEnvAdaptor implements IApixEnvAdaptor {
export enum EnvAdaptorConstants {
LOCALSTORAGE_SDK_LANGUAGE_KEY = 'sdkLanguage',
}

let envAdaptor: IApixEnvAdaptor | undefined

/**
* Register the environment adaptor. The API Explorer will automatically call this.
*/
export const registerEnvAdaptor = (adaptor: IApixEnvAdaptor) => {
envAdaptor = adaptor
}

/**
* Unregister the envAdaptor. The API Explorer will automatically call this when it is unmounted.
*/
export const unregisterEnvAdaptor = () => {
envAdaptor = undefined
}

/**
* Global access to the envAdaptor. An error will be thrown if accessed prematurely.
*/
export const getEnvAdaptor = () => {
if (!envAdaptor) {
throw new Error('Environment adaptor not initialized.')
}
return envAdaptor
}

0 comments on commit 9a9d9fe

Please sign in to comment.