Frontend brain dump.

Signed-off-by: Eric Peterson <ericpeterson@spotify.com>
This commit is contained in:
Eric Peterson
2021-05-24 14:57:33 +02:00
parent f86171027e
commit 62fcca6b9e
2 changed files with 190 additions and 27 deletions
+32 -9
View File
@@ -10,12 +10,16 @@ Backstage Search is _blah_.
To get started, you should get familiar with these core concepts:
TODO: Link these like a real TOC
- Search Engines
- Query Translators
- Documents and Indices
- Collators
- Decorators
- The Scheduler
- The Search Page
- Search Context and Components
### Search Engines
@@ -23,8 +27,8 @@ Backstage Search isn't a search engine itself, rather, it provides an interface
between your Backstage instance and a Search Engine of your choice. More
concretely, a `SearchEngine` is an interface whose concrete implementations
facilitate communication with different search engines (like ElasticSearch,
Solr, Algolia, etc). This abstraction exists in order to support your
organization's needs.
Solr, etc). This abstraction exists in order to support your organization's
needs.
Out of the box, Backstage Search comes pre-packaged with an in-memory search
engine implementation built on top of Lunr.
@@ -39,7 +43,7 @@ search engine.
Search Engines come pre-packaged with simple translators that do rudimentary
transformations of search terms and filters, but you may want to provide your
own to help tune seearch results in the context of your organization.
own to help tune search results in the context of your organization.
### Documents and Indices
@@ -78,11 +82,30 @@ Search chooses to completely rebuild indices on a schedule. Different collators
can be configured to refresh at different intervals, depending on how often the
source information is updated.
TODO: There should probably be some front-end concepts here too?
### The Search Page
- Search Page
- Search Components
- Search Context
Search pages are very custom things. Not every Backstage instance will want the
same interface! In order to allow you to customize your search experience to
your heart's content, the Search Plugin takes care of state management and other
search logic for you, but most of the layout of a search page lives in a search
page component defined in your Backstage App.
[Primarily solves for “As an App Integrator, I should know how to add do uments
to the search index”]
For an example of a simple search page, check [getting started](TODO)
### Search Context and Components
A search experience, like a page, is composed of any number of search
components, which are all wired up using a search context.
Each search experience's context consists of details like a search term,
filters, types, results, and a page cursor for handling pagination. Different
components use this context in different ways, for example the `<SearchBar />`
can set the search term, `<SearchFilter />` components can set filters, and
search results can be displayed using the `<SearchResult />` component.
The `<SearchResult />` and `<SearchFilter />` components are special, in that
they themselves are extensible. For an example of how to extend these
components, [check this out](TODO).
If you need even more customization, you can use the search context like any
other React context to create custom search components of your own.
+158 -18
View File
@@ -12,9 +12,9 @@ use Search.
If you haven't setup Backstage already, start
[here](../../getting-started/index.md).
> If you used `npx @backstage/create-app`, Search may already be present.
>
> You should skip to [`Customizing Search`](#customizing-search) below.
> If you used `npx @backstage/create-app`, and you have a search page defined in
> `packages/app/src/components/search`, skip to
> [`Customizing Search`](#customizing-search) below.
## Adding Search to the Frontend
@@ -24,7 +24,92 @@ cd packages/app
yarn add @backstage/plugin-search
```
TODO: Add frontend instructions here.
Create a new `packages/app/src/components/search/SearchPage.tsx` file in your
Backstage app with the following contents:
```tsx
import React from 'react';
import { Content, Header, Page } from '@backstage/core';
import { Grid, List, Card, CardContent } from '@material-ui/core';
import {
SearchBar,
SearchResult,
DefaultResultListItem,
SearchFilter,
} from '@backstage/plugin-search';
import { CatalogResultListItem } from '@backstage/plugin-catalog';
export const searchPage = (
<Page themeId="home">
<Header title="Search" />
<Content>
<Grid container direction="row">
<Grid item xs={12}>
<SearchBar />
</Grid>
<Grid item xs={3}>
<Card>
<CardContent>
<SearchFilter.Select
name="kind"
values={['Component', 'Template']}
/>
</CardContent>
<CardContent>
<SearchFilter.Checkbox
name="lifecycle"
values={['experimental', 'production']}
/>
</CardContent>
</Card>
</Grid>
<Grid item xs={9}>
<SearchResult>
{({ results }) => (
<List>
{results.map(result => {
switch (result.type) {
case 'software-catalog':
return (
<CatalogResultListItem
key={result.document.location}
result={result.document}
/>
);
default:
return (
<DefaultResultListItem
key={result.document.location}
result={result.document}
/>
);
}
})}
</List>
)}
</SearchResult>
</Grid>
</Grid>
</Content>
</Page>
);
```
Bind the above Search Page to the `/search` route in your
`packages/app/src/App.tsx` file, like this:
```tsx
import { SearchPage } from '@backstage/plugin-search';
import { searchPage } from './components/search/SearchPage';
const routes = (
<FlatRoutes>
<Route path="/search" element={<SearchPage />}>
{searchPage}
</Route>
</FlatRoutes>
);
```
## Adding Search to the Backend
@@ -96,6 +181,75 @@ apiRouter.use('/search', await search(searchEnv));
## Customizing Search
### Frontend
The Search Plugin exposes several default filter types as static properties,
including `<SearchFilter.Select />` and `<SearchFilter.Checkbox />`. These allow
you to provide values relevant to your Backstage instance that, when selected,
get passed to the backend.
```tsx {2-5,8-11}
<CardContent>
<SearchFilter.Select
name="kind"
values={['Component', 'Template']}
/>
</CardContent>
<CardContent>
<SearchFilter.Checkbox
name="lifecycle"
values={['production', 'experimental']}
/>
</CardContent>
```
If you have advanced filter needs, you can specify your own filter component
like this (although contributions are welcome):
```tsx
import { useSearch, SearchFilter } from '@backstage/plugin-search';
const MyCustomFilter = () => {
// Note: filters contain filter data from other filter components. Be sure
// not to clobber other filters' data!
const { filters, setFilters } = useSearch();
return (/* ... */);
};
// Which could be rendered like this:
<SearchFilter component={MyCustomFilter} />
```
It's good practice for search results to highlight information that was used to
return it in the first place! The code below highlights how you might specify a
custom result item component, using the `<CatalogResultListItem />` component as
an example:
```tsx {7-13}
<SearchResult>
{({ results }) => (
<List>
{results.map(result => {
// result.type is the index type defined by the collator.
switch (result.type) {
case 'software-catalog':
return (
<CatalogResultListItem
key={result.document.location}
result={result.document}
/>
);
// ...
}
})}
</List>
)}
</SearchResult>
```
### Backend
Backstage Search isn't a search engine itself, rather, it provides an interface
between your Backstage instance and a Search Engine of your choice. Currently,
we only support one, in-memory search Engine called Lunr. It can be instantiated
@@ -139,17 +293,3 @@ indexBuilder.addCollator({
collator: new DefaultCatalogCollator({ discovery }),
});
```
---
[Primarily solves for “As an App Integrator, I should be able to install out-of
the-box Search”]
Backend: Different for new Backstage instances (created via create-app) vs.
people enabling search on existing Backstage instances (see catalog install for
example).
Frontend: Search Page Route…? Customizing result components…?
Conceptually… Whats the difference between “out-of-the-box” or “basic” and the
recommended deployment (which will come)