diff --git a/.changeset/breezy-cobras-deny.md b/.changeset/breezy-cobras-deny.md new file mode 100644 index 0000000000..5f035c05ce --- /dev/null +++ b/.changeset/breezy-cobras-deny.md @@ -0,0 +1,5 @@ +--- +'@backstage/core': patch +--- + +Clear sidebar search field once a search is executed diff --git a/.changeset/small-worms-check.md b/.changeset/small-worms-check.md new file mode 100644 index 0000000000..e39265f8f9 --- /dev/null +++ b/.changeset/small-worms-check.md @@ -0,0 +1,6 @@ +--- +'example-app': patch +'@backstage/plugin-search': patch +--- + +Using the search field in the sidebar now navigates to the search result page. diff --git a/packages/app/src/components/Root/Root.tsx b/packages/app/src/components/Root/Root.tsx index e947e5c91d..47e7d32d1a 100644 --- a/packages/app/src/components/Root/Root.tsx +++ b/packages/app/src/components/Root/Root.tsx @@ -33,12 +33,12 @@ import { SidebarContext, SidebarItem, SidebarDivider, - SidebarSearchField, SidebarSpace, } from '@backstage/core'; import { NavLink } from 'react-router-dom'; import { graphiQLRouteRef } from '@backstage/plugin-graphiql'; import { Settings as SidebarSettings } from '@backstage/plugin-user-settings'; +import { SidebarSearch } from '@backstage/plugin-search'; const useSidebarLogoStyles = makeStyles({ root: { @@ -73,17 +73,11 @@ const SidebarLogo: FC<{}> = () => { ); }; -const handleSearch = (query: string): void => { - // XXX (@koroeskohr): for testing purposes - // eslint-disable-next-line no-console - console.log(query); -}; - const Root: FC<{}> = ({ children }) => ( - + {/* Global nav, not org-specific */} diff --git a/packages/core/src/hooks/useQueryParamState.ts b/packages/core/src/hooks/useQueryParamState.ts index 9317dcd3e1..dc2279cb53 100644 --- a/packages/core/src/hooks/useQueryParamState.ts +++ b/packages/core/src/hooks/useQueryParamState.ts @@ -14,8 +14,9 @@ * limitations under the License. */ +import { isEqual } from 'lodash'; import qs from 'qs'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useLocation, useNavigate } from 'react-router-dom'; import { useDebounce } from 'react-use'; @@ -64,6 +65,14 @@ export function useQueryParamState( extractState(location.search, stateName), ); + useEffect(() => { + const newState = extractState(location.search, stateName); + + setQueryParamState(oldState => + isEqual(newState, oldState) ? oldState : newState, + ); + }, [location, stateName]); + useDebounce( () => { const queryString = joinQueryString( diff --git a/packages/core/src/layout/Sidebar/Items.tsx b/packages/core/src/layout/Sidebar/Items.tsx index bb47701280..498946577d 100644 --- a/packages/core/src/layout/Sidebar/Items.tsx +++ b/packages/core/src/layout/Sidebar/Items.tsx @@ -221,6 +221,7 @@ export const SidebarSearchField: FC = props => { const handleEnter: KeyboardEventHandler = ev => { if (ev.key === 'Enter') { props.onSearch(input); + setInput(''); } }; @@ -233,6 +234,7 @@ export const SidebarSearchField: FC = props => { { - const [searchQuery, setSearchQuery] = useState(''); + const [queryString, setQueryString] = useQueryParamState('query'); + const [searchQuery, setSearchQuery] = useState(queryString ?? ''); const handleSearch = (event: React.ChangeEvent) => { event.preventDefault(); setSearchQuery(event.target.value); }; + useEffect(() => setSearchQuery(queryString ?? ''), [queryString]); + + useDebounce( + () => { + setQueryString(searchQuery); + }, + 200, + [searchQuery], + ); + const handleClearSearchBar = () => { setSearchQuery(''); }; @@ -46,7 +56,7 @@ export const SearchPage = () => { /> - + diff --git a/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx b/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx new file mode 100644 index 0000000000..6a279e0743 --- /dev/null +++ b/plugins/search/src/components/SidebarSearch/SidebarSearch.tsx @@ -0,0 +1,35 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import React, { useCallback } from 'react'; +import qs from 'qs'; +import { useNavigate } from 'react-router-dom'; +import { SidebarSearchField } from '@backstage/core'; + +export const SidebarSearch = () => { + const navigate = useNavigate(); + const handleSearch = useCallback( + (query: string): void => { + const queryString = qs.stringify({ query }, { addQueryPrefix: true }); + + // TODO: Here the url to the search plugin is hardcoded. We need a way to query the route in the future. + // Maybe an API that I can just call from other places? + navigate(`/search${queryString}`); + }, + [navigate], + ); + + return ; +}; diff --git a/plugins/search/src/components/SidebarSearch/index.ts b/plugins/search/src/components/SidebarSearch/index.ts new file mode 100644 index 0000000000..33869ffb77 --- /dev/null +++ b/plugins/search/src/components/SidebarSearch/index.ts @@ -0,0 +1,16 @@ +/* + * Copyright 2020 Spotify AB + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +export { SidebarSearch } from './SidebarSearch'; diff --git a/plugins/search/src/components/index.tsx b/plugins/search/src/components/index.tsx index f8e6a5a09e..ac47860dc2 100644 --- a/plugins/search/src/components/index.tsx +++ b/plugins/search/src/components/index.tsx @@ -18,3 +18,4 @@ export * from './Filters'; export * from './SearchBar'; export * from './SearchPage'; export * from './SearchResult'; +export * from './SidebarSearch'; diff --git a/plugins/search/src/index.ts b/plugins/search/src/index.ts index 224e293890..77ad7f9266 100644 --- a/plugins/search/src/index.ts +++ b/plugins/search/src/index.ts @@ -14,3 +14,4 @@ * limitations under the License. */ export { plugin } from './plugin'; +export * from './components';