feat(search-react): add use parent context prop

Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
Camila Belo
2022-08-26 12:42:38 +02:00
parent af7594d587
commit 412825d9eb
3 changed files with 49 additions and 37 deletions
@@ -101,28 +101,20 @@ const searchInitialState: SearchContextState = {
};
/**
* Props for {@link SearchContextProvider}
*
* @public
* Creates a new local search context.
* @remarks Use it for isolating this context from parent search contexts.
* @internal
*/
export type SearchContextProviderProps = PropsWithChildren<{
initialState?: SearchContextState;
}>;
/**
* @public
*
* Search context provider which gives you access to shared state between search components
*/
export const SearchContextProvider = (props: SearchContextProviderProps) => {
const { initialState = searchInitialState, children } = props;
const useSearchContextValue = (
initialValue: SearchContextState = searchInitialState,
) => {
const searchApi = useApi(searchApiRef);
const [pageCursor, setPageCursor] = useState<string | undefined>(
initialState.pageCursor,
initialValue.pageCursor,
);
const [filters, setFilters] = useState<JsonObject>(initialState.filters);
const [term, setTerm] = useState<string>(initialState.term);
const [types, setTypes] = useState<string[]>(initialState.types);
const [filters, setFilters] = useState<JsonObject>(initialValue.filters);
const [term, setTerm] = useState<string>(initialValue.term);
const [types, setTypes] = useState<string[]>(initialValue.types);
const prevTerm = usePrevious(term);
@@ -170,11 +162,41 @@ export const SearchContextProvider = (props: SearchContextProviderProps) => {
fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,
};
const versionedValue = createVersionedValueMap({ 1: value });
return value;
};
return (
<AnalyticsContext attributes={{ searchTypes: types.sort().join(',') }}>
<SearchContext.Provider value={versionedValue} children={children} />
/**
* Props for {@link SearchContextProvider}
*
* @public
*/
export type SearchContextProviderProps = PropsWithChildren<{
initialState?: SearchContextState;
/**
* If true, don't create a child context if there is a parent one already defined.
* @remarks Default to false.
*/
useParentContext?: boolean;
}>;
/**
* @public
* Search context provider which gives you access to shared state between search components
*/
export const SearchContextProvider = (props: SearchContextProviderProps) => {
const { initialState, useParentContext, children } = props;
const hasParentContext = useSearchContextCheck();
const value = useSearchContextValue(initialState);
return useParentContext && hasParentContext ? (
<>{children}</>
) : (
<AnalyticsContext
attributes={{ searchTypes: value.types.sort().join(',') }}
>
<SearchContext.Provider value={createVersionedValueMap({ 1: value })}>
{children}
</SearchContext.Provider>
</AnalyticsContext>
);
};
@@ -55,7 +55,7 @@ describe('SearchModal', () => {
);
expect(screen.getByRole('dialog')).toBeInTheDocument();
expect(query).toHaveBeenCalledTimes(1);
expect(query).toHaveBeenCalledTimes(2);
});
it('Should use parent search context if defined', async () => {
@@ -133,7 +133,7 @@ describe('SearchModal', () => {
},
);
expect(query).toHaveBeenCalledTimes(1);
expect(query).toHaveBeenCalledTimes(2);
await userEvent.keyboard('{Escape}');
expect(toggleModal).toHaveBeenCalledTimes(1);
});
@@ -14,7 +14,7 @@
* limitations under the License.
*/
import React, { PropsWithChildren } from 'react';
import React from 'react';
import {
Dialog,
DialogActions,
@@ -35,7 +35,6 @@ import {
SearchResult,
SearchResultPager,
useSearch,
useSearchContextCheck,
} from '@backstage/plugin-search-react';
import { useRouteRef } from '@backstage/core-plugin-api';
import { Link, useContent } from '@backstage/core-components';
@@ -171,15 +170,6 @@ export const Modal = ({ toggleModal }: SearchModalProps) => {
);
};
const Context = ({ children }: PropsWithChildren<{}>) => {
// Checks if there is a parent context already defined and, if not, creates a new local context.
const hasParentContext = useSearchContextCheck();
if (hasParentContext) {
return <>{children}</>;
}
return <SearchContextProvider>{children}</SearchContextProvider>;
};
/**
* @public
*/
@@ -204,11 +194,11 @@ export const SearchModal = ({
hidden={hidden}
>
{open && (
<Context>
<SearchContextProvider useParentContext>
{(children && children({ toggleModal })) ?? (
<Modal toggleModal={toggleModal} />
)}
</Context>
</SearchContextProvider>
)}
</Dialog>
);