From 42b3615b042436c8e8ea7876f8d48c6abb6c66fe Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Fri, 4 Jun 2021 17:50:53 +0200 Subject: [PATCH] -> , with deprecation warning. Signed-off-by: Eric Peterson --- .../app/src/components/search/SearchPage.tsx | 2 +- .../SearchResult.test.tsx} | 20 +- .../components/SearchResult/SearchResult.tsx | 249 ++---------------- .../src/components/SearchResult/index.tsx | 2 +- .../SearchResultNext/SearchResultNext.tsx | 49 ---- .../src/components/SearchResultNext/index.tsx | 17 -- plugins/search/src/components/index.tsx | 1 - plugins/search/src/index.ts | 3 +- plugins/search/src/plugin.ts | 17 +- 9 files changed, 42 insertions(+), 318 deletions(-) rename plugins/search/src/components/{SearchResultNext/SearchResultNext.test.tsx => SearchResult/SearchResult.test.tsx} (82%) delete mode 100644 plugins/search/src/components/SearchResultNext/SearchResultNext.tsx delete mode 100644 plugins/search/src/components/SearchResultNext/index.tsx diff --git a/packages/app/src/components/search/SearchPage.tsx b/packages/app/src/components/search/SearchPage.tsx index 221d4a44c4..5d977807bd 100644 --- a/packages/app/src/components/search/SearchPage.tsx +++ b/packages/app/src/components/search/SearchPage.tsx @@ -22,7 +22,7 @@ import { CatalogResultListItem } from '@backstage/plugin-catalog'; import { SearchBarNext as SearchBar, SearchFilterNext as SearchFilter, - SearchResultNext as SearchResult, + SearchResult, DefaultResultListItem, } from '@backstage/plugin-search'; diff --git a/plugins/search/src/components/SearchResultNext/SearchResultNext.test.tsx b/plugins/search/src/components/SearchResult/SearchResult.test.tsx similarity index 82% rename from plugins/search/src/components/SearchResultNext/SearchResultNext.test.tsx rename to plugins/search/src/components/SearchResult/SearchResult.test.tsx index 98fc285265..2beb47b157 100644 --- a/plugins/search/src/components/SearchResultNext/SearchResultNext.test.tsx +++ b/plugins/search/src/components/SearchResult/SearchResult.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { render, waitFor } from '@testing-library/react'; -import { SearchResultNext } from './SearchResultNext'; +import { SearchResult } from './SearchResult'; import { useSearch } from '../SearchContext'; jest.mock('../SearchContext', () => ({ @@ -27,15 +27,13 @@ jest.mock('../SearchContext', () => ({ }), })); -describe('SearchResultNext', () => { +describe('SearchResult', () => { it('Progress rendered on Loading state', async () => { (useSearch as jest.Mock).mockReturnValueOnce({ result: { loading: true }, }); - const { getByRole } = render( - {() => <>}, - ); + const { getByRole } = render({() => <>}); await waitFor(() => { expect(getByRole('progressbar')).toBeInTheDocument(); @@ -48,9 +46,7 @@ describe('SearchResultNext', () => { result: { loading: false, error }, }); - const { getByRole } = render( - {() => <>}, - ); + const { getByRole } = render({() => <>}); await waitFor(() => { expect(getByRole('alert')).toHaveTextContent( @@ -64,9 +60,7 @@ describe('SearchResultNext', () => { result: { loading: false, error: '', value: undefined }, }); - const { getByRole } = render( - {() => <>}, - ); + const { getByRole } = render({() => <>}); await waitFor(() => { expect( @@ -81,12 +75,12 @@ describe('SearchResultNext', () => { }); render( - + {({ results }) => { expect(results).toEqual([]); return <>; }} - , + , ); }); }); diff --git a/plugins/search/src/components/SearchResult/SearchResult.tsx b/plugins/search/src/components/SearchResult/SearchResult.tsx index 0aa209e6fe..24b582f7e9 100644 --- a/plugins/search/src/components/SearchResult/SearchResult.tsx +++ b/plugins/search/src/components/SearchResult/SearchResult.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -13,162 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - EmptyState, - Link, - Progress, - Table, - TableColumn, - useApi, -} from '@backstage/core'; -import { Divider, Grid, makeStyles, Typography } from '@material-ui/core'; + +import React from 'react'; +import { EmptyState, Progress } from '@backstage/core'; +import { SearchResult } from '@backstage/search-common'; import { Alert } from '@material-ui/lab'; -import React, { useEffect, useState } from 'react'; -import { useAsync } from 'react-use'; -import { Result, SearchResults, searchApiRef } from '../../apis'; -import { Filters, FiltersButton, FiltersState } from '../Filters'; +import { useSearch } from '../SearchContext'; -const useStyles = makeStyles(theme => ({ - searchQuery: { - color: theme.palette.text.primary, - background: theme.palette.background.default, - borderRadius: '10%', - }, - tableHeader: { - margin: theme.spacing(1, 0, 0, 0), - display: 'flex', - }, - divider: { - width: '1px', - margin: theme.spacing(0, 2), - padding: theme.spacing(2, 0), - }, -})); - -type SearchResultProps = { - searchQuery?: string; +type Props = { + children: (results: { results: SearchResult[] }) => JSX.Element; }; -type TableHeaderProps = { - searchQuery?: string; - numberOfSelectedFilters: number; - numberOfResults: number; - handleToggleFilters: () => void; -}; +const SearchResultComponent = ({ children }: Props) => { + const { + result: { loading, error, value }, + } = useSearch(); -// TODO: move out column to make the search result component more generic -const columns: TableColumn[] = [ - { - title: 'Name', - field: 'name', - highlight: true, - render: (result: Partial) => ( - {result.name} - ), - }, - { - title: 'Description', - field: 'description', - }, - { - title: 'Owner', - field: 'owner', - }, - { - title: 'Kind', - field: 'kind', - }, - { - title: 'LifeCycle', - field: 'lifecycle', - }, -]; - -const TableHeader = ({ - searchQuery, - numberOfSelectedFilters, - numberOfResults, - handleToggleFilters, -}: TableHeaderProps) => { - const classes = useStyles(); - - return ( -
- - - - {searchQuery ? ( - - {`${numberOfResults} `} - {numberOfResults > 1 ? `results for ` : `result for `} - "{searchQuery}"{' '} - - ) : ( - {`${numberOfResults} results`} - )} - -
- ); -}; - -export const SearchResult = ({ searchQuery }: SearchResultProps) => { - const searchApi = useApi(searchApiRef); - - const [showFilters, toggleFilters] = useState(false); - const [selectedFilters, setSelectedFilters] = useState({ - selected: '', - checked: [], - }); - - const [filteredResults, setFilteredResults] = useState([]); - - const { loading, error, value: results } = useAsync(() => { - return searchApi.getSearchResult(); - }, []); - - useEffect(() => { - if (results) { - let withFilters = results; - - // apply filters - - // filter on selected - if (selectedFilters.selected !== '') { - withFilters = results.filter((result: Result) => - selectedFilters.selected.includes(result.kind), - ); - } - - // filter on checked - if (selectedFilters.checked.length > 0) { - withFilters = withFilters.filter( - (result: Result) => - result.lifecycle && - selectedFilters.checked.includes(result.lifecycle), - ); - } - - // filter on searchQuery - if (searchQuery) { - withFilters = withFilters.filter( - (result: Result) => - result.name?.toLocaleLowerCase('en-US').includes(searchQuery) || - result.name - ?.toLocaleLowerCase('en-US') - .includes(searchQuery.split(' ').join('-')) || - result.description - ?.toLocaleLowerCase('en-US') - .includes(searchQuery), - ); - } - - setFilteredResults(withFilters); - } - }, [selectedFilters, searchQuery, results]); if (loading) { return ; } @@ -179,88 +40,12 @@ export const SearchResult = ({ searchQuery }: SearchResultProps) => { ); } - if (!results || results.length === 0) { + + if (!value) { return ; } - const resetFilters = () => { - setSelectedFilters({ - selected: '', - checked: [], - }); - }; - - const updateSelected = (filter: string) => { - setSelectedFilters(prevState => ({ - ...prevState, - selected: filter, - })); - }; - - const updateChecked = (filter: string) => { - if (selectedFilters.checked.includes(filter)) { - setSelectedFilters(prevState => ({ - ...prevState, - checked: prevState.checked.filter(item => item !== filter), - })); - return; - } - - setSelectedFilters(prevState => ({ - ...prevState, - checked: [...prevState.checked, filter], - })); - }; - - const filterOptions = results.reduce( - (acc, curr) => { - if (curr.kind && acc.kind.indexOf(curr.kind) < 0) { - acc.kind.push(curr.kind); - } - if (curr.lifecycle && acc.lifecycle.indexOf(curr.lifecycle) < 0) { - acc.lifecycle.push(curr.lifecycle); - } - return acc; - }, - { - kind: [] as Array, - lifecycle: [] as Array, - }, - ); - - return ( - <> - - {showFilters && ( - - - - )} - - toggleFilters(!showFilters)} - /> - } - /> - - - - ); + return children({ results: value.results }); }; + +export { SearchResultComponent as SearchResult }; diff --git a/plugins/search/src/components/SearchResult/index.tsx b/plugins/search/src/components/SearchResult/index.tsx index cf10135fd0..407700c19c 100644 --- a/plugins/search/src/components/SearchResult/index.tsx +++ b/plugins/search/src/components/SearchResult/index.tsx @@ -1,5 +1,5 @@ /* - * Copyright 2020 Spotify AB + * Copyright 2021 Spotify AB * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/plugins/search/src/components/SearchResultNext/SearchResultNext.tsx b/plugins/search/src/components/SearchResultNext/SearchResultNext.tsx deleted file mode 100644 index 84d3759ad3..0000000000 --- a/plugins/search/src/components/SearchResultNext/SearchResultNext.tsx +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2021 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 { EmptyState, Progress } from '@backstage/core'; -import { SearchResult } from '@backstage/search-common'; -import { Alert } from '@material-ui/lab'; - -import { useSearch } from '../SearchContext'; - -type Props = { - children: (results: { results: SearchResult[] }) => JSX.Element; -}; - -export const SearchResultNext = ({ children }: Props) => { - const { - result: { loading, error, value }, - } = useSearch(); - - if (loading) { - return ; - } - if (error) { - return ( - - Error encountered while fetching search results. {error.toString()} - - ); - } - - if (!value) { - return ; - } - - return children({ results: value.results }); -}; diff --git a/plugins/search/src/components/SearchResultNext/index.tsx b/plugins/search/src/components/SearchResultNext/index.tsx deleted file mode 100644 index 73fabfdc7d..0000000000 --- a/plugins/search/src/components/SearchResultNext/index.tsx +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright 2021 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 { SearchResultNext } from './SearchResultNext'; diff --git a/plugins/search/src/components/index.tsx b/plugins/search/src/components/index.tsx index 40d5c3603d..3032cda0b7 100644 --- a/plugins/search/src/components/index.tsx +++ b/plugins/search/src/components/index.tsx @@ -20,7 +20,6 @@ export * from './SearchBar'; export * from './SearchBarNext'; export * from './SearchPage'; export * from './SearchResult'; -export * from './SearchResultNext'; export * from './DefaultResultListItem'; export * from './SidebarSearch'; export * from './SearchContext'; diff --git a/plugins/search/src/index.ts b/plugins/search/src/index.ts index 27fd1706fc..26f1c8f544 100644 --- a/plugins/search/src/index.ts +++ b/plugins/search/src/index.ts @@ -21,7 +21,7 @@ export { SearchPage, SearchPageNext, SearchBarNext, - SearchResultNext, + SearchResult, DefaultResultListItem, } from './plugin'; export { @@ -32,7 +32,6 @@ export { useSearch, SearchPage as Router, SearchFilterNext, - SearchResult, SidebarSearch, } from './components'; export type { FiltersState } from './components'; diff --git a/plugins/search/src/plugin.ts b/plugins/search/src/plugin.ts index 01abf38df9..24eb049d42 100644 --- a/plugins/search/src/plugin.ts +++ b/plugins/search/src/plugin.ts @@ -80,11 +80,24 @@ export const SearchBarNext = searchPlugin.provide( }), ); +export const SearchResult = searchPlugin.provide( + createComponentExtension({ + component: { + lazy: () => import('./components/SearchResult').then(m => m.SearchResult), + }, + }), +); + +/** + * @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 SearchResultNext = searchPlugin.provide( createComponentExtension({ component: { - lazy: () => - import('./components/SearchResultNext').then(m => m.SearchResultNext), + lazy: () => import('./components/SearchResult').then(m => m.SearchResult), }, }), );