Merge pull request #8302 from backstage/feat/search-modal-context
[Search] Search Modal now relies on the Search Context
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
---
|
||||
'@backstage/create-app': patch
|
||||
---
|
||||
|
||||
Search Modal now relies on the Search Context to access state and state setter. If you use the SidebarSearchModal as described in the [getting started documentation](https://backstage.io/docs/features/search/getting-started#using-the-search-modal), make sure to update your code with the SearchContextProvider.
|
||||
|
||||
```diff
|
||||
export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
- <SidebarSearchModal />
|
||||
+ <SearchContextProvider>
|
||||
+ <SidebarSearchModal />
|
||||
+ </SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
...
|
||||
```
|
||||
@@ -0,0 +1,18 @@
|
||||
---
|
||||
'@backstage/plugin-search': minor
|
||||
---
|
||||
|
||||
Search Modal now relies on the Search Context to access state and state setter. If you use the SidebarSearchModal as described in the [getting started documentation](https://backstage.io/docs/features/search/getting-started#using-the-search-modal), make sure to update your code with the SearchContextProvider.
|
||||
|
||||
```diff
|
||||
export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
- <SidebarSearchModal />
|
||||
+ <SearchContextProvider>
|
||||
+ <SidebarSearchModal />
|
||||
+ </SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
...
|
||||
```
|
||||
@@ -114,13 +114,15 @@ const routes = (
|
||||
In `Root.tsx`, add the `SidebarSearchModal` component:
|
||||
|
||||
```bash
|
||||
import { SidebarSearchModal } from '@backstage/plugin-search';
|
||||
import { SidebarSearchModal, SearchContextProvider } from '@backstage/plugin-search';
|
||||
|
||||
export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
<SidebarSearchModal />
|
||||
<SearchContextProvider>
|
||||
<SidebarSearchModal />
|
||||
</SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
...
|
||||
```
|
||||
|
||||
@@ -29,7 +29,10 @@ import LogoIcon from './LogoIcon';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { GraphiQLIcon } from '@backstage/plugin-graphiql';
|
||||
import { Settings as SidebarSettings } from '@backstage/plugin-user-settings';
|
||||
import { SidebarSearchModal } from '@backstage/plugin-search';
|
||||
import {
|
||||
SidebarSearchModal,
|
||||
SearchContextProvider,
|
||||
} from '@backstage/plugin-search';
|
||||
import { Shortcuts } from '@backstage/plugin-shortcuts';
|
||||
import {
|
||||
Sidebar,
|
||||
@@ -80,7 +83,9 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
<SidebarSearchModal />
|
||||
<SearchContextProvider>
|
||||
<SidebarSearchModal />
|
||||
</SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
{/* Global nav, not org-specific */}
|
||||
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
|
||||
|
||||
@@ -25,7 +25,10 @@ import LogoFull from './LogoFull';
|
||||
import LogoIcon from './LogoIcon';
|
||||
import { NavLink } from 'react-router-dom';
|
||||
import { Settings as SidebarSettings } from '@backstage/plugin-user-settings';
|
||||
import { SidebarSearchModal } from '@backstage/plugin-search';
|
||||
import {
|
||||
SidebarSearchModal,
|
||||
SearchContextProvider,
|
||||
} from '@backstage/plugin-search';
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarPage,
|
||||
@@ -74,7 +77,9 @@ export const Root = ({ children }: PropsWithChildren<{}>) => (
|
||||
<SidebarPage>
|
||||
<Sidebar>
|
||||
<SidebarLogo />
|
||||
<SidebarSearchModal />
|
||||
<SearchContextProvider>
|
||||
<SidebarSearchModal />
|
||||
</SearchContextProvider>
|
||||
<SidebarDivider />
|
||||
{/* Global nav, not org-specific */}
|
||||
<SidebarItem icon={HomeIcon} to="catalog" text="Home" />
|
||||
|
||||
@@ -221,7 +221,7 @@ export const useSearch: () => SearchContextValue;
|
||||
|
||||
// Warnings were encountered during analysis:
|
||||
//
|
||||
// src/components/SearchContext/SearchContext.d.ts:21:5 - (ae-forgotten-export) The symbol "SettableSearchContext" needs to be exported by the entry point index.d.ts
|
||||
// src/components/SearchContext/SearchContext.d.ts:23:5 - (ae-forgotten-export) The symbol "SettableSearchContext" needs to be exported by the entry point index.d.ts
|
||||
// src/components/SearchFilter/SearchFilter.d.ts:13:5 - (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
// src/components/SearchFilter/SearchFilter.d.ts:14:5 - (ae-forgotten-export) The symbol "Component" needs to be exported by the entry point index.d.ts
|
||||
```
|
||||
|
||||
@@ -37,6 +37,8 @@ type SearchContextValue = {
|
||||
setTypes: React.Dispatch<React.SetStateAction<string[]>>;
|
||||
filters: JsonObject;
|
||||
setFilters: React.Dispatch<React.SetStateAction<JsonObject>>;
|
||||
open?: boolean;
|
||||
toggleModal: () => void;
|
||||
pageCursor?: string;
|
||||
setPageCursor: React.Dispatch<React.SetStateAction<string | undefined>>;
|
||||
fetchNextPage?: React.DispatchWithoutAction;
|
||||
@@ -49,6 +51,7 @@ type SettableSearchContext = Omit<
|
||||
| 'setTerm'
|
||||
| 'setTypes'
|
||||
| 'setFilters'
|
||||
| 'toggleModal'
|
||||
| 'setPageCursor'
|
||||
| 'fetchNextPage'
|
||||
| 'fetchPreviousPage'
|
||||
@@ -74,6 +77,12 @@ export const SearchContextProvider = ({
|
||||
const [filters, setFilters] = useState<JsonObject>(initialState.filters);
|
||||
const [term, setTerm] = useState<string>(initialState.term);
|
||||
const [types, setTypes] = useState<string[]>(initialState.types);
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const toggleModal = useCallback(
|
||||
(): void => setOpen(prevState => !prevState),
|
||||
[],
|
||||
);
|
||||
|
||||
const prevTerm = usePrevious(term);
|
||||
|
||||
const result = useAsync(
|
||||
@@ -109,6 +118,8 @@ export const SearchContextProvider = ({
|
||||
result,
|
||||
filters,
|
||||
setFilters,
|
||||
open,
|
||||
toggleModal,
|
||||
term,
|
||||
setTerm,
|
||||
types,
|
||||
|
||||
@@ -14,28 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import React, { useState, ComponentType } from 'react';
|
||||
import React, { ComponentType } from 'react';
|
||||
import { Button } from '@material-ui/core';
|
||||
import { ApiProvider, ApiRegistry } from '@backstage/core-app-api';
|
||||
import { wrapInTestApp } from '@backstage/test-utils';
|
||||
import { SearchModal } from '../index';
|
||||
import { useSearch, SearchContextProvider } from '../SearchContext';
|
||||
import { searchApiRef } from '../../apis';
|
||||
import { rootRouteRef } from '../../plugin';
|
||||
|
||||
export default {
|
||||
title: 'Plugins/Search/SearchModal',
|
||||
component: SearchModal,
|
||||
decorators: [
|
||||
(Story: ComponentType<{}>) =>
|
||||
wrapInTestApp(
|
||||
<>
|
||||
<Story />
|
||||
</>,
|
||||
{ mountedRoutes: { '/search': rootRouteRef } },
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
const mockSearchApi = {
|
||||
query: () =>
|
||||
Promise.resolve({
|
||||
@@ -70,16 +57,33 @@ const mockSearchApi = {
|
||||
|
||||
const apiRegistry = () => ApiRegistry.from([[searchApiRef, mockSearchApi]]);
|
||||
|
||||
export default {
|
||||
title: 'Plugins/Search/SearchModal',
|
||||
component: SearchModal,
|
||||
decorators: [
|
||||
(Story: ComponentType<{}>) =>
|
||||
wrapInTestApp(
|
||||
<>
|
||||
<ApiProvider apis={apiRegistry()}>
|
||||
<SearchContextProvider>
|
||||
<Story />
|
||||
</SearchContextProvider>
|
||||
</ApiProvider>
|
||||
</>,
|
||||
{ mountedRoutes: { '/search': rootRouteRef } },
|
||||
),
|
||||
],
|
||||
};
|
||||
|
||||
export const Default = () => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const toggleModal = (): void => setOpen(prevState => !prevState);
|
||||
const { open, toggleModal } = useSearch();
|
||||
|
||||
return (
|
||||
<ApiProvider apis={apiRegistry()}>
|
||||
<>
|
||||
<Button variant="contained" color="primary" onClick={toggleModal}>
|
||||
Toggle Search Modal
|
||||
</Button>
|
||||
<SearchModal open={open} toggleModal={toggleModal} />
|
||||
</ApiProvider>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -13,14 +13,14 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { useState } from 'react';
|
||||
import React from 'react';
|
||||
import SearchIcon from '@material-ui/icons/Search';
|
||||
import { SearchModal } from '../SearchModal';
|
||||
import { SidebarItem } from '@backstage/core-components';
|
||||
import { SearchModal } from '../SearchModal';
|
||||
import { useSearch } from '../SearchContext';
|
||||
|
||||
export const SidebarSearchModal = () => {
|
||||
const [open, setOpen] = useState<boolean>(false);
|
||||
const toggleModal = (): void => setOpen(prevState => !prevState);
|
||||
const { open, toggleModal } = useSearch();
|
||||
|
||||
return (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user