diff --git a/packages/app/src/App.tsx b/packages/app/src/App.tsx
index 5874465ef6..b14f9a3163 100644
--- a/packages/app/src/App.tsx
+++ b/packages/app/src/App.tsx
@@ -43,7 +43,7 @@ import { GraphiQLPage } from '@backstage/plugin-graphiql';
import { LighthousePage } from '@backstage/plugin-lighthouse';
import { NewRelicPage } from '@backstage/plugin-newrelic';
import { ScaffolderPage, scaffolderPlugin } from '@backstage/plugin-scaffolder';
-import { SearchPage, SearchPageNext } from '@backstage/plugin-search';
+import { SearchPage } from '@backstage/plugin-search';
import { TechRadarPage } from '@backstage/plugin-tech-radar';
import { TechdocsPage } from '@backstage/plugin-techdocs';
import { UserSettingsPage } from '@backstage/plugin-user-settings';
@@ -119,8 +119,7 @@ const routes = (
} />
} />
} />
- } />
- }>
+ }>
{searchPage}
} />
diff --git a/plugins/search/src/components/SearchPageNext/SearchPageNext.test.tsx b/plugins/search/src/components/SearchPage/SearchPage.test.tsx
similarity index 83%
rename from plugins/search/src/components/SearchPageNext/SearchPageNext.test.tsx
rename to plugins/search/src/components/SearchPage/SearchPage.test.tsx
index 5890f8cf41..20bfb707cf 100644
--- a/plugins/search/src/components/SearchPageNext/SearchPageNext.test.tsx
+++ b/plugins/search/src/components/SearchPage/SearchPage.test.tsx
@@ -16,17 +16,17 @@
import React from 'react';
import { renderInTestApp } from '@backstage/test-utils';
-import { useLocation, Outlet } from 'react-router';
+import { useLocation, useOutlet } from 'react-router';
import { useSearch, SearchContextProvider } from '../SearchContext';
-import { SearchPageNext } from './';
+import { SearchPage } from './';
jest.mock('react-router', () => ({
...jest.requireActual('react-router'),
useLocation: jest.fn().mockReturnValue({
search: '',
}),
- Outlet: jest.fn().mockReturnValue(null),
+ useOutlet: jest.fn().mockReturnValue('Route Children'),
}));
jest.mock('../SearchContext', () => ({
@@ -68,7 +68,7 @@ describe('SearchPage', () => {
});
// When we render the page...
- await renderInTestApp();
+ await renderInTestApp();
// Then search context should be initialized with these values...
const calls = (SearchContextProvider as jest.Mock).mock.calls[0];
@@ -80,9 +80,16 @@ describe('SearchPage', () => {
});
it('renders provided router element', async () => {
- await renderInTestApp();
+ const { getByText } = await renderInTestApp();
- expect(Outlet).toHaveBeenCalled();
+ expect(getByText('Route Children')).toBeInTheDocument();
+ });
+
+ it('renders upgrade error whe no router children are provided', async () => {
+ (useOutlet as jest.Mock).mockReturnValueOnce(null);
+ const { getByText } = await renderInTestApp();
+
+ expect(getByText('Error: No Search Layout Found')).toBeInTheDocument();
});
it('replaces window history with expected query parameters', async () => {
@@ -96,7 +103,7 @@ describe('SearchPage', () => {
'?query=bieber&types[]=software-catalog&pageCursor=page2-or-something&filters[anyKey]=anyValue',
);
- await renderInTestApp();
+ await renderInTestApp();
const calls = (window.history.replaceState as jest.Mock).mock.calls[0];
expect(calls[2]).toContain(expectedLocation);
diff --git a/plugins/search/src/components/SearchPage/SearchPage.tsx b/plugins/search/src/components/SearchPage/SearchPage.tsx
index 7c216fc908..5eb84c689c 100644
--- a/plugins/search/src/components/SearchPage/SearchPage.tsx
+++ b/plugins/search/src/components/SearchPage/SearchPage.tsx
@@ -13,55 +13,81 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import { Content, Header, Page, useQueryParamState } from '@backstage/core';
-import { Grid } from '@material-ui/core';
-import React, { useEffect, useState } from 'react';
-import { useDebounce } from 'react-use';
-import { SearchBar } from '../SearchBar';
-import { SearchResult } from '../SearchResult';
-export const SearchPage = () => {
- 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('');
- };
+import React from 'react';
+import qs from 'qs';
+import { useLocation, useOutlet } from 'react-router';
+import { SearchContextProvider, useSearch } from '../SearchContext';
+import { JsonObject } from '@backstage/config';
+import { Content, Header, Page, Link, WarningPanel } from '@backstage/core';
+const UpdateInstructions = () => {
return (
-
-
-
-
-
-
-
-
+
+ As of v0.4.0 of the Backstage Search Plugin, a search layout must
+ be provided by the App. For detailed instructions, check the{' '}
+
+ getting started guide
+
+ .
+ >
+ }
+ />
);
};
+
+export const UrlUpdater = () => {
+ const { term, types, pageCursor, filters } = useSearch();
+
+ const newParams = qs.stringify(
+ {
+ query: term,
+ types,
+ pageCursor,
+ filters,
+ },
+ { arrayFormat: 'brackets' },
+ );
+ const newUrl = `${window.location.pathname}?${newParams}`;
+
+ // We directly manipulate window history here in order to not re-render
+ // infinitely (state => location => state => etc). The intention of this
+ // code is just to ensure the right query/filters are loaded when a user
+ // clicks the "back" button after clicking a result.
+ window.history.replaceState(null, document.title, newUrl);
+
+ return null;
+};
+
+export const SearchPage = () => {
+ const location = useLocation();
+ const outlet = useOutlet();
+ const query = qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {};
+ const filters = (query.filters as JsonObject) || {};
+ const queryString = (query.query as string) || '';
+ const pageCursor = (query.pageCursor as string) || '';
+ const types = (query.types as string[]) || [];
+
+ const initialState = {
+ term: queryString || '',
+ types,
+ pageCursor,
+ filters,
+ };
+
+ return (
+
+
+ {outlet || }
+
+ );
+};
diff --git a/plugins/search/src/components/SearchPageNext/SearchPageNext.tsx b/plugins/search/src/components/SearchPageNext/SearchPageNext.tsx
deleted file mode 100644
index f851778ddf..0000000000
--- a/plugins/search/src/components/SearchPageNext/SearchPageNext.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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 from 'react';
-import qs from 'qs';
-import { Outlet, useLocation } from 'react-router';
-import { SearchContextProvider, useSearch } from '../SearchContext';
-import { JsonObject } from '@backstage/config';
-
-export const UrlUpdater = () => {
- const { term, types, pageCursor, filters } = useSearch();
-
- const newParams = qs.stringify(
- {
- query: term,
- types,
- pageCursor,
- filters,
- },
- { arrayFormat: 'brackets' },
- );
- const newUrl = `${window.location.pathname}?${newParams}`;
-
- // We directly manipulate window history here in order to not re-render
- // infinitely (state => location => state => etc). The intention of this
- // code is just to ensure the right query/filters are loaded when a user
- // clicks the "back" button after clicking a result.
- window.history.replaceState(null, document.title, newUrl);
-
- return null;
-};
-
-export const SearchPageNext = () => {
- const location = useLocation();
- const query = qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {};
- const filters = (query.filters as JsonObject) || {};
- const queryString = (query.query as string) || '';
- const pageCursor = (query.pageCursor as string) || '';
- const types = (query.types as string[]) || [];
-
- const initialState = {
- term: queryString || '',
- types,
- pageCursor,
- filters,
- };
-
- return (
-
-
-
-
- );
-};
diff --git a/plugins/search/src/components/SearchPageNext/index.tsx b/plugins/search/src/components/SearchPageNext/index.tsx
deleted file mode 100644
index 464ba28750..0000000000
--- a/plugins/search/src/components/SearchPageNext/index.tsx
+++ /dev/null
@@ -1,17 +0,0 @@
-/*
- * 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 { SearchPageNext } from './SearchPageNext';
diff --git a/plugins/search/src/components/index.tsx b/plugins/search/src/components/index.tsx
index 92e24b60df..40d5c3603d 100644
--- a/plugins/search/src/components/index.tsx
+++ b/plugins/search/src/components/index.tsx
@@ -19,7 +19,6 @@ export * from './SearchFilterNext';
export * from './SearchBar';
export * from './SearchBarNext';
export * from './SearchPage';
-export * from './SearchPageNext';
export * from './SearchResult';
export * from './SearchResultNext';
export * from './DefaultResultListItem';
diff --git a/plugins/search/src/plugin.ts b/plugins/search/src/plugin.ts
index 6ff40ebaf7..01abf38df9 100644
--- a/plugins/search/src/plugin.ts
+++ b/plugins/search/src/plugin.ts
@@ -23,8 +23,6 @@ import {
} from '@backstage/core';
import { SearchClient, searchApiRef } from './apis';
import { catalogApiRef } from '@backstage/plugin-catalog-react';
-import { SearchPage as SearchPageComponent } from './components/SearchPage';
-import { SearchPageNext as SearchPageNextComponent } from './components/SearchPageNext';
export const rootRouteRef = createRouteRef({
path: '/search',
@@ -47,10 +45,6 @@ export const searchPlugin = createPlugin({
},
}),
],
- register({ router }) {
- router.addRoute(rootRouteRef, SearchPageComponent);
- router.addRoute(rootNextRouteRef, SearchPageNextComponent);
- },
routes: {
root: rootRouteRef,
nextRoot: rootNextRouteRef,
@@ -64,10 +58,15 @@ export const SearchPage = searchPlugin.provide(
}),
);
+/**
+ * @deprecated This component was used for rapid prototyping of the Backstage
+ * Search platform. Now that the API has stabilized, you should use the
+ * component instead. This component will be removed in an
+ * upcoming release.
+ */
export const SearchPageNext = searchPlugin.provide(
createRoutableExtension({
- component: () =>
- import('./components/SearchPageNext').then(m => m.SearchPageNext),
+ component: () => import('./components/SearchPage').then(m => m.SearchPage),
mountPoint: rootNextRouteRef,
}),
);