@backstage/plugin-search 0.4.12 → 0.4.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +46 -0
- package/dist/esm/{index-b832898d.esm.js → index-3eebaa65.esm.js} +2 -2
- package/dist/esm/{index-b832898d.esm.js.map → index-3eebaa65.esm.js.map} +1 -1
- package/dist/esm/{index-03e6e5c1.esm.js → index-4ef7a5c8.esm.js} +2 -2
- package/dist/esm/index-4ef7a5c8.esm.js.map +1 -0
- package/dist/esm/{index-5da0411f.esm.js → index-6f14e751.esm.js} +2 -2
- package/dist/esm/index-6f14e751.esm.js.map +1 -0
- package/dist/esm/{index-f5f6f3f0.esm.js → index-9c0d67e6.esm.js} +24 -11
- package/dist/esm/index-9c0d67e6.esm.js.map +1 -0
- package/dist/esm/{index-329be754.esm.js → index-ee8d2563.esm.js} +2 -2
- package/dist/esm/{index-329be754.esm.js.map → index-ee8d2563.esm.js.map} +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.esm.js +1 -1
- package/package.json +17 -16
- package/dist/esm/index-03e6e5c1.esm.js.map +0 -1
- package/dist/esm/index-5da0411f.esm.js.map +0 -1
- package/dist/esm/index-f5f6f3f0.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,51 @@
|
|
|
1
1
|
# @backstage/plugin-search
|
|
2
2
|
|
|
3
|
+
## 0.4.16
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 10615525f3: Switch to use the json and observable types from `@backstage/types`
|
|
8
|
+
- Updated dependencies
|
|
9
|
+
- @backstage/config@0.1.11
|
|
10
|
+
- @backstage/theme@0.2.12
|
|
11
|
+
- @backstage/errors@0.1.4
|
|
12
|
+
- @backstage/core-components@0.7.2
|
|
13
|
+
- @backstage/plugin-catalog-react@0.6.2
|
|
14
|
+
- @backstage/catalog-model@0.9.6
|
|
15
|
+
- @backstage/search-common@0.2.1
|
|
16
|
+
- @backstage/core-plugin-api@0.1.12
|
|
17
|
+
|
|
18
|
+
## 0.4.15
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 56bd537256: SearchBar component to accept optional placeholder prop
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @backstage/plugin-catalog-react@0.6.0
|
|
25
|
+
- @backstage/core-components@0.7.0
|
|
26
|
+
- @backstage/theme@0.2.11
|
|
27
|
+
|
|
28
|
+
## 0.4.14
|
|
29
|
+
|
|
30
|
+
### Patch Changes
|
|
31
|
+
|
|
32
|
+
- ca0559444c: Avoid usage of `.to*Case()`, preferring `.toLocale*Case('en-US')` instead.
|
|
33
|
+
- 81a41ec249: Added a `name` key to all extensions in order to improve Analytics API metadata.
|
|
34
|
+
- Updated dependencies
|
|
35
|
+
- @backstage/core-components@0.6.1
|
|
36
|
+
- @backstage/core-plugin-api@0.1.10
|
|
37
|
+
- @backstage/plugin-catalog-react@0.5.2
|
|
38
|
+
- @backstage/catalog-model@0.9.4
|
|
39
|
+
|
|
40
|
+
## 0.4.13
|
|
41
|
+
|
|
42
|
+
### Patch Changes
|
|
43
|
+
|
|
44
|
+
- Updated dependencies
|
|
45
|
+
- @backstage/core-plugin-api@0.1.9
|
|
46
|
+
- @backstage/core-components@0.6.0
|
|
47
|
+
- @backstage/plugin-catalog-react@0.5.1
|
|
48
|
+
|
|
3
49
|
## 0.4.12
|
|
4
50
|
|
|
5
51
|
### Patch Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useCallback } from 'react';
|
|
2
2
|
import { makeStyles } from '@material-ui/core/styles';
|
|
3
|
-
import { r as rootRouteRef, b as SearchBarBase } from './index-
|
|
3
|
+
import { r as rootRouteRef, b as SearchBarBase } from './index-9c0d67e6.esm.js';
|
|
4
4
|
import qs from 'qs';
|
|
5
5
|
import { useNavigate } from 'react-router-dom';
|
|
6
6
|
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
@@ -56,4 +56,4 @@ const HomePageSearchBar = ({placeholder}) => {
|
|
|
56
56
|
};
|
|
57
57
|
|
|
58
58
|
export { HomePageSearchBar };
|
|
59
|
-
//# sourceMappingURL=index-
|
|
59
|
+
//# sourceMappingURL=index-3eebaa65.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-3eebaa65.esm.js","sources":["../../src/components/util.ts","../../src/components/HomePageComponent/HomePageSearchBar.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport qs from 'qs';\nimport { useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { rootRouteRef } from '../plugin';\n\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nexport const useNavigateToQuery = () => {\n const searchRoute = useRouteRef(rootRouteRef);\n const navigate = useNavigate();\n return useCallback(\n ({ query }: { query: string }): void => {\n const queryString = qs.stringify({ query }, { addQueryPrefix: true });\n\n navigate(`${searchRoute()}${queryString}`);\n },\n [navigate, searchRoute],\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport { SearchBarBase } from '../SearchBar';\nimport { useNavigateToQuery } from '../util';\n\nconst useStyles = makeStyles({\n searchBar: {\n border: '1px solid #555',\n borderRadius: '6px',\n fontSize: '1.5em',\n },\n});\n\ntype Props = {\n placeholder?: string;\n};\n\nexport const HomePageSearchBar = ({ placeholder }: Props) => {\n const [query, setQuery] = React.useState('');\n const handleSearch = useNavigateToQuery();\n const classes = useStyles();\n\n const handleSubmit = () => {\n handleSearch({ query });\n };\n\n const handleChange = React.useCallback(\n value => {\n setQuery(value);\n },\n [setQuery],\n );\n\n return (\n <SearchBarBase\n onSubmit={handleSubmit}\n onChange={handleChange}\n value={query}\n className={classes.searchBar}\n placeholder={placeholder}\n />\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;MAsBa,qBAAqB,MAAM;AACtC,QAAM,cAAc,YAAY;AAChC,QAAM,WAAW;AACjB,SAAO,YACL,CAAC,CAAE,WAAqC;AACtC,UAAM,cAAc,GAAG,UAAU,CAAE,QAAS,CAAE,gBAAgB;AAE9D,aAAS,GAAG,gBAAgB;AAAA,KAE9B,CAAC,UAAU;AAAA;;ACTf,MAAM,YAAY,WAAW;AAAA,EAC3B,WAAW;AAAA,IACT,QAAQ;AAAA,IACR,cAAc;AAAA,IACd,UAAU;AAAA;AAAA;MAQD,oBAAoB,CAAC,CAAE,iBAAyB;AAC3D,QAAM,CAAC,OAAO,YAAY,MAAM,SAAS;AACzC,QAAM,eAAe;AACrB,QAAM,UAAU;AAEhB,QAAM,eAAe,MAAM;AACzB,iBAAa,CAAE;AAAA;AAGjB,QAAM,eAAe,MAAM,YACzB,WAAS;AACP,aAAS;AAAA,KAEX,CAAC;AAGH,6CACG,eAAD;AAAA,IACE,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW,QAAQ;AAAA,IACnB;AAAA;AAAA;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { S as SearchPage } from './index-
|
|
1
|
+
export { S as SearchPage } from './index-9c0d67e6.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -19,4 +19,4 @@ import '@backstage/catalog-model';
|
|
|
19
19
|
import '@material-ui/icons/ArrowBackIos';
|
|
20
20
|
import '@material-ui/icons/ArrowForwardIos';
|
|
21
21
|
import 'react-router-dom';
|
|
22
|
-
//# sourceMappingURL=index-
|
|
22
|
+
//# sourceMappingURL=index-4ef7a5c8.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-4ef7a5c8.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { a as SearchBar, b as SearchBarBase } from './index-
|
|
1
|
+
export { a as SearchBar, b as SearchBarBase } from './index-9c0d67e6.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -19,4 +19,4 @@ import '@backstage/catalog-model';
|
|
|
19
19
|
import '@material-ui/icons/ArrowBackIos';
|
|
20
20
|
import '@material-ui/icons/ArrowForwardIos';
|
|
21
21
|
import 'react-router-dom';
|
|
22
|
-
//# sourceMappingURL=index-
|
|
22
|
+
//# sourceMappingURL=index-6f14e751.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-6f14e751.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -244,7 +244,11 @@ const SearchBarBase = ({
|
|
|
244
244
|
...onSubmit && {onKeyDown}
|
|
245
245
|
});
|
|
246
246
|
};
|
|
247
|
-
const SearchBar$1 = ({
|
|
247
|
+
const SearchBar$1 = ({
|
|
248
|
+
className,
|
|
249
|
+
debounceTime = 0,
|
|
250
|
+
placeholder
|
|
251
|
+
}) => {
|
|
248
252
|
const {term, setTerm} = useSearch();
|
|
249
253
|
const [value, setValue] = useState(term);
|
|
250
254
|
useEffect(() => {
|
|
@@ -259,7 +263,8 @@ const SearchBar$1 = ({className, debounceTime = 0}) => {
|
|
|
259
263
|
className,
|
|
260
264
|
value,
|
|
261
265
|
onChange: handleQuery,
|
|
262
|
-
onClear: handleClear
|
|
266
|
+
onClear: handleClear,
|
|
267
|
+
placeholder
|
|
263
268
|
});
|
|
264
269
|
};
|
|
265
270
|
|
|
@@ -598,7 +603,7 @@ const SearchResult$1 = ({searchQuery}) => {
|
|
|
598
603
|
owner: typeof ((_a = entity.spec) == null ? void 0 : _a.owner) === "string" ? (_b = entity.spec) == null ? void 0 : _b.owner : void 0,
|
|
599
604
|
kind: entity.kind,
|
|
600
605
|
lifecycle: typeof ((_c = entity.spec) == null ? void 0 : _c.lifecycle) === "string" ? (_d = entity.spec) == null ? void 0 : _d.lifecycle : void 0,
|
|
601
|
-
url: `/catalog/${((_e = entity.metadata.namespace) == null ? void 0 : _e.
|
|
606
|
+
url: `/catalog/${((_e = entity.metadata.namespace) == null ? void 0 : _e.toLocaleLowerCase("en-US")) || ENTITY_DEFAULT_NAMESPACE}/${entity.kind.toLocaleLowerCase("en-US")}/${entity.metadata.name}`
|
|
602
607
|
};
|
|
603
608
|
});
|
|
604
609
|
}, []);
|
|
@@ -905,41 +910,49 @@ const searchPlugin = createPlugin({
|
|
|
905
910
|
}
|
|
906
911
|
});
|
|
907
912
|
const SearchPage = searchPlugin.provide(createRoutableExtension({
|
|
908
|
-
|
|
913
|
+
name: "SearchPage",
|
|
914
|
+
component: () => import('./index-4ef7a5c8.esm.js').then((m) => m.SearchPage),
|
|
909
915
|
mountPoint: rootRouteRef
|
|
910
916
|
}));
|
|
911
917
|
const SearchPageNext = searchPlugin.provide(createRoutableExtension({
|
|
912
|
-
|
|
918
|
+
name: "SearchPageNext",
|
|
919
|
+
component: () => import('./index-4ef7a5c8.esm.js').then((m) => m.SearchPage),
|
|
913
920
|
mountPoint: rootNextRouteRef
|
|
914
921
|
}));
|
|
915
922
|
searchPlugin.provide(createComponentExtension({
|
|
923
|
+
name: "SearchBar",
|
|
916
924
|
component: {
|
|
917
|
-
lazy: () => import('./index-
|
|
925
|
+
lazy: () => import('./index-6f14e751.esm.js').then((m) => m.SearchBar)
|
|
918
926
|
}
|
|
919
927
|
}));
|
|
920
928
|
const SearchBarNext = searchPlugin.provide(createComponentExtension({
|
|
929
|
+
name: "SearchBarNext",
|
|
921
930
|
component: {
|
|
922
|
-
lazy: () => import('./index-
|
|
931
|
+
lazy: () => import('./index-6f14e751.esm.js').then((m) => m.SearchBar)
|
|
923
932
|
}
|
|
924
933
|
}));
|
|
925
934
|
const SearchResult = searchPlugin.provide(createComponentExtension({
|
|
935
|
+
name: "SearchResult",
|
|
926
936
|
component: {
|
|
927
|
-
lazy: () => import('./index-
|
|
937
|
+
lazy: () => import('./index-ee8d2563.esm.js').then((m) => m.SearchResult)
|
|
928
938
|
}
|
|
929
939
|
}));
|
|
930
940
|
searchPlugin.provide(createComponentExtension({
|
|
941
|
+
name: "SearchResultNext",
|
|
931
942
|
component: {
|
|
932
|
-
lazy: () => import('./index-
|
|
943
|
+
lazy: () => import('./index-ee8d2563.esm.js').then((m) => m.SearchResult)
|
|
933
944
|
}
|
|
934
945
|
}));
|
|
935
946
|
const DefaultResultListItem = searchPlugin.provide(createComponentExtension({
|
|
947
|
+
name: "DefaultResultListItem",
|
|
936
948
|
component: {
|
|
937
949
|
lazy: () => import('./index-92a9e2ec.esm.js').then((m) => m.DefaultResultListItem)
|
|
938
950
|
}
|
|
939
951
|
}));
|
|
940
952
|
const HomePageSearchBar = searchPlugin.provide(createComponentExtension({
|
|
953
|
+
name: "HomePageSearchBar",
|
|
941
954
|
component: {
|
|
942
|
-
lazy: () => import('./index-
|
|
955
|
+
lazy: () => import('./index-3eebaa65.esm.js').then((m) => m.HomePageSearchBar)
|
|
943
956
|
}
|
|
944
957
|
}));
|
|
945
958
|
|
|
@@ -957,4 +970,4 @@ const SidebarSearch = () => {
|
|
|
957
970
|
};
|
|
958
971
|
|
|
959
972
|
export { DefaultResultListItem as D, Filters$1 as F, HomePageSearchBar as H, SearchPage$1 as S, SearchBar$1 as a, SearchBarBase as b, FiltersButton$1 as c, SearchContextProvider as d, SearchFilter as e, SearchFilterNext as f, SearchResultPager as g, SearchType as h, SidebarSearch as i, SearchBarNext as j, SearchPage as k, SearchPageNext as l, searchPlugin as m, SearchResult as n, rootRouteRef as r, searchApiRef as s, useSearch as u };
|
|
960
|
-
//# sourceMappingURL=index-
|
|
973
|
+
//# sourceMappingURL=index-9c0d67e6.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-9c0d67e6.esm.js","sources":["../../src/apis.ts","../../src/components/Filters/FiltersButton.tsx","../../src/components/Filters/Filters.tsx","../../src/components/SearchContext/SearchContext.tsx","../../src/components/SearchBar/SearchBar.tsx","../../src/components/SearchFilter/SearchFilter.tsx","../../src/components/LegacySearchPage/LegacySearchBar.tsx","../../src/components/LegacySearchPage/Filters/FiltersButton.tsx","../../src/components/LegacySearchPage/Filters/Filters.tsx","../../src/components/LegacySearchPage/LegacySearchResult.tsx","../../src/components/LegacySearchPage/LegacySearchPage.tsx","../../src/components/SearchPage/SearchPage.tsx","../../src/components/SearchResultPager/SearchResultPager.tsx","../../src/components/SearchType/SearchType.tsx","../../src/plugin.ts","../../src/components/SidebarSearch/SidebarSearch.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { SearchQuery, SearchResultSet } from '@backstage/search-common';\nimport qs from 'qs';\n\nexport const searchApiRef = createApiRef<SearchApi>({\n id: 'plugin.search.queryservice',\n description: 'Used to make requests against the search API',\n});\n\nexport interface SearchApi {\n query(query: SearchQuery): Promise<SearchResultSet>;\n}\n\nexport class SearchClient implements SearchApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n async query(query: SearchQuery): Promise<SearchResultSet> {\n const token = await this.identityApi.getIdToken();\n const queryString = qs.stringify(query);\n const url = `${await this.discoveryApi.getBaseUrl(\n 'search/query',\n )}?${queryString}`;\n const response = await fetch(url, {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { makeStyles, IconButton, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n width: '250px',\n display: 'flex',\n },\n icon: {\n margin: theme.spacing(-1, 0, 0, 0),\n },\n}));\n\ntype FiltersButtonProps = {\n numberOfSelectedFilters: number;\n handleToggleFilters: () => void;\n};\n\nexport const FiltersButton = ({\n numberOfSelectedFilters,\n handleToggleFilters,\n}: FiltersButtonProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.filters}>\n <IconButton\n className={classes.icon}\n aria-label=\"settings\"\n onClick={handleToggleFilters}\n >\n <FilterListIcon />\n </IconButton>\n <Typography variant=\"h6\">\n Filters ({numberOfSelectedFilters ? numberOfSelectedFilters : 0})\n </Typography>\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n makeStyles,\n Typography,\n Divider,\n Card,\n CardHeader,\n Button,\n CardContent,\n Select,\n Checkbox,\n List,\n ListItem,\n ListItemText,\n MenuItem,\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n background: 'transparent',\n boxShadow: '0px 0px 0px 0px',\n },\n checkbox: {\n padding: theme.spacing(0, 1, 0, 1),\n },\n dropdown: {\n width: '100%',\n },\n}));\n\nexport type FiltersState = {\n selected: string;\n checked: Array<string>;\n};\n\nexport type FilterOptions = {\n kind: Array<string>;\n lifecycle: Array<string>;\n};\n\ntype FiltersProps = {\n filters: FiltersState;\n filterOptions: FilterOptions;\n resetFilters: () => void;\n updateSelected: (filter: string) => void;\n updateChecked: (filter: string) => void;\n};\n\nexport const Filters = ({\n filters,\n filterOptions,\n resetFilters,\n updateSelected,\n updateChecked,\n}: FiltersProps) => {\n const classes = useStyles();\n\n return (\n <Card className={classes.filters}>\n <CardHeader\n title={<Typography variant=\"h6\">Filters</Typography>}\n action={\n <Button color=\"primary\" onClick={() => resetFilters()}>\n CLEAR ALL\n </Button>\n }\n />\n <Divider />\n {filterOptions.kind.length === 0 && filterOptions.lifecycle.length === 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">\n Filters cannot be applied to available results\n </Typography>\n </CardContent>\n )}\n {filterOptions.kind.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Kind</Typography>\n <Select\n id=\"outlined-select\"\n onChange={(e: React.ChangeEvent<any>) =>\n updateSelected(e?.target?.value)\n }\n variant=\"outlined\"\n className={classes.dropdown}\n value={filters.selected}\n >\n {filterOptions.kind.map(filter => (\n <MenuItem\n selected={filter === ''}\n dense\n key={filter}\n value={filter}\n >\n {filter}\n </MenuItem>\n ))}\n </Select>\n </CardContent>\n )}\n {filterOptions.lifecycle.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Lifecycle</Typography>\n <List disablePadding dense>\n {filterOptions.lifecycle.map(filter => (\n <ListItem\n key={filter}\n dense\n button\n onClick={() => updateChecked(filter)}\n >\n <Checkbox\n edge=\"start\"\n disableRipple\n className={classes.checkbox}\n color=\"primary\"\n checked={filters.checked.includes(filter)}\n tabIndex={-1}\n value={filter}\n name={filter}\n />\n <ListItemText id={filter} primary={filter} />\n </ListItem>\n ))}\n </List>\n </CardContent>\n )}\n </Card>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/types';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { SearchResultSet } from '@backstage/search-common';\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { useAsync, usePrevious } from 'react-use';\nimport { AsyncState } from 'react-use/lib/useAsync';\nimport { searchApiRef } from '../../apis';\n\ntype SearchContextValue = {\n result: AsyncState<SearchResultSet>;\n term: string;\n setTerm: React.Dispatch<React.SetStateAction<string>>;\n types: string[];\n setTypes: React.Dispatch<React.SetStateAction<string[]>>;\n filters: JsonObject;\n setFilters: React.Dispatch<React.SetStateAction<JsonObject>>;\n pageCursor?: string;\n setPageCursor: React.Dispatch<React.SetStateAction<string | undefined>>;\n fetchNextPage?: React.DispatchWithoutAction;\n fetchPreviousPage?: React.DispatchWithoutAction;\n};\n\ntype SettableSearchContext = Omit<\n SearchContextValue,\n | 'result'\n | 'setTerm'\n | 'setTypes'\n | 'setFilters'\n | 'setPageCursor'\n | 'fetchNextPage'\n | 'fetchPreviousPage'\n>;\n\nexport const SearchContext = createContext<SearchContextValue | undefined>(\n undefined,\n);\n\nexport const SearchContextProvider = ({\n initialState = {\n term: '',\n pageCursor: undefined,\n filters: {},\n types: [],\n },\n children,\n}: PropsWithChildren<{ initialState?: SettableSearchContext }>) => {\n const searchApi = useApi(searchApiRef);\n const [pageCursor, setPageCursor] = useState<string | undefined>(\n initialState.pageCursor,\n );\n const [filters, setFilters] = useState<JsonObject>(initialState.filters);\n const [term, setTerm] = useState<string>(initialState.term);\n const [types, setTypes] = useState<string[]>(initialState.types);\n const prevTerm = usePrevious(term);\n\n const result = useAsync(\n () =>\n searchApi.query({\n term,\n filters,\n pageCursor: pageCursor,\n types,\n }),\n [term, filters, types, pageCursor],\n );\n\n const hasNextPage =\n !result.loading && !result.error && result.value?.nextPageCursor;\n const hasPreviousPage =\n !result.loading && !result.error && result.value?.previousPageCursor;\n const fetchNextPage = useCallback(() => {\n setPageCursor(result.value?.nextPageCursor);\n }, [result.value?.nextPageCursor]);\n const fetchPreviousPage = useCallback(() => {\n setPageCursor(result.value?.previousPageCursor);\n }, [result.value?.previousPageCursor]);\n\n useEffect(() => {\n // Any time a term is reset, we want to start from page 0.\n if (term && prevTerm && term !== prevTerm) {\n setPageCursor(undefined);\n }\n }, [term, prevTerm, initialState.pageCursor]);\n\n const value: SearchContextValue = {\n result,\n filters,\n setFilters,\n term,\n setTerm,\n types,\n setTypes,\n pageCursor,\n setPageCursor,\n fetchNextPage: hasNextPage ? fetchNextPage : undefined,\n fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,\n };\n\n return <SearchContext.Provider value={value} children={children} />;\n};\n\nexport const useSearch = () => {\n const context = useContext(SearchContext);\n if (context === undefined) {\n throw new Error('useSearch must be used within a SearchContextProvider');\n }\n return context;\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, KeyboardEvent, useState } from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { useDebounce } from 'react-use';\nimport { InputBase, InputAdornment, IconButton } from '@material-ui/core';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ClearButton from '@material-ui/icons/Clear';\n\nimport { useSearch } from '../SearchContext';\n\ntype PresenterProps = {\n value: string;\n onChange: (value: string) => void;\n onClear?: () => void;\n onSubmit?: () => void;\n className?: string;\n placeholder?: string;\n};\n\nexport const SearchBarBase = ({\n value,\n onChange,\n onSubmit,\n className,\n placeholder: overridePlaceholder,\n}: PresenterProps) => {\n const configApi = useApi(configApiRef);\n\n const onKeyDown = React.useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onSubmit],\n );\n\n const handleClear = React.useCallback(() => {\n onChange('');\n }, [onChange]);\n\n const placeholder =\n overridePlaceholder ??\n `Search in ${configApi.getOptionalString('app.title') || 'Backstage'}`;\n\n return (\n <InputBase\n data-testid=\"search-bar-next\"\n fullWidth\n placeholder={placeholder}\n value={value}\n onChange={e => onChange(e.target.value)}\n inputProps={{ 'aria-label': 'Search' }}\n startAdornment={\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n }\n endAdornment={\n <InputAdornment position=\"end\">\n <IconButton aria-label=\"Clear\" onClick={handleClear}>\n <ClearButton />\n </IconButton>\n </InputAdornment>\n }\n {...(className && { className })}\n {...(onSubmit && { onKeyDown })}\n />\n );\n};\n\ntype Props = {\n className?: string;\n debounceTime?: number;\n placeholder?: string;\n};\n\nexport const SearchBar = ({\n className,\n debounceTime = 0,\n placeholder,\n}: Props) => {\n const { term, setTerm } = useSearch();\n const [value, setValue] = useState<string>(term);\n\n useEffect(() => {\n setValue(prevValue => (prevValue !== term ? term : prevValue));\n }, [term]);\n\n useDebounce(() => setTerm(value), debounceTime, [value]);\n\n const handleQuery = (newValue: string) => {\n setValue(newValue);\n };\n\n const handleClear = () => setValue('');\n\n return (\n <SearchBarBase\n className={className}\n value={value}\n onChange={handleQuery}\n onClear={handleClear}\n placeholder={placeholder}\n />\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { ReactElement, ChangeEvent, useEffect } from 'react';\nimport {\n makeStyles,\n FormControl,\n FormControlLabel,\n InputLabel,\n Checkbox,\n Select,\n MenuItem,\n FormLabel,\n} from '@material-ui/core';\n\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles({\n label: {\n textTransform: 'capitalize',\n },\n});\n\nexport type Component = {\n className?: string;\n name: string;\n values?: string[];\n defaultValue?: string[] | string | null;\n};\n\nexport type Props = Component & {\n component: (props: Component) => ReactElement;\n debug?: boolean;\n};\n\nconst CheckboxFilter = ({\n className,\n name,\n defaultValue,\n values = [],\n}: Component) => {\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n\n useEffect(() => {\n if (Array.isArray(defaultValue)) {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n const {\n target: { value, checked },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n const rest = ((filter as string[]) || []).filter(i => i !== value);\n const items = checked ? [...rest, value] : rest;\n return items.length ? { ...others, [name]: items } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n fullWidth\n data-testid=\"search-checkboxfilter-next\"\n >\n <FormLabel className={classes.label}>{name}</FormLabel>\n {values.map((value: string) => (\n <FormControlLabel\n key={value}\n control={\n <Checkbox\n color=\"primary\"\n tabIndex={-1}\n inputProps={{ 'aria-labelledby': value }}\n value={value}\n name={value}\n onChange={handleChange}\n checked={((filters[name] as string[]) ?? []).includes(value)}\n />\n }\n label={value}\n />\n ))}\n </FormControl>\n );\n};\n\nconst SelectFilter = ({\n className,\n name,\n defaultValue,\n values = [],\n}: Component) => {\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n\n useEffect(() => {\n if (typeof defaultValue === 'string') {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleChange = (e: ChangeEvent<{ value: unknown }>) => {\n const {\n target: { value },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n return value ? { ...others, [name]: value as string } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-selectfilter-next\"\n >\n <InputLabel className={classes.label} margin=\"dense\">\n {name}\n </InputLabel>\n <Select\n variant=\"outlined\"\n value={filters[name] || ''}\n onChange={handleChange}\n >\n <MenuItem value=\"\">\n <em>All</em>\n </MenuItem>\n {values.map((value: string) => (\n <MenuItem key={value} value={value}>\n {value}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n\nconst SearchFilter = ({ component: Element, ...props }: Props) => (\n <Element {...props} />\n);\n\nSearchFilter.Checkbox = (props: Omit<Props, 'component'> & Component) => (\n <SearchFilter {...props} component={CheckboxFilter} />\n);\n\nSearchFilter.Select = (props: Omit<Props, 'component'> & Component) => (\n <SearchFilter {...props} component={SelectFilter} />\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchFilter /> component instead. This component will be removed in an\n * upcoming release.\n */\nconst SearchFilterNext = SearchFilter;\n\nexport { SearchFilter, SearchFilterNext };\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { Paper } from '@material-ui/core';\nimport InputBase from '@material-ui/core/InputBase';\nimport IconButton from '@material-ui/core/IconButton';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ClearButton from '@material-ui/icons/Clear';\n\nconst useStyles = makeStyles(() => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n },\n input: {\n flex: 1,\n },\n}));\n\ntype SearchBarProps = {\n searchQuery: string;\n handleSearch: any;\n handleClearSearchBar: any;\n};\n\nexport const SearchBar = ({\n searchQuery,\n handleSearch,\n handleClearSearchBar,\n}: SearchBarProps) => {\n const classes = useStyles();\n\n return (\n <Paper\n component=\"form\"\n onSubmit={e => handleSearch(e)}\n className={classes.root}\n >\n <IconButton disabled type=\"submit\" aria-label=\"search\">\n <SearchIcon />\n </IconButton>\n <InputBase\n className={classes.input}\n placeholder=\"Search in Backstage\"\n value={searchQuery}\n onChange={e => handleSearch(e)}\n inputProps={{ 'aria-label': 'search backstage' }}\n />\n <IconButton aria-label=\"search\" onClick={() => handleClearSearchBar()}>\n <ClearButton />\n </IconButton>\n </Paper>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { makeStyles, IconButton, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n width: '250px',\n display: 'flex',\n },\n icon: {\n margin: theme.spacing(-1, 0, 0, 0),\n },\n}));\n\ntype FiltersButtonProps = {\n numberOfSelectedFilters: number;\n handleToggleFilters: () => void;\n};\n\nexport const FiltersButton = ({\n numberOfSelectedFilters,\n handleToggleFilters,\n}: FiltersButtonProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.filters}>\n <IconButton\n className={classes.icon}\n aria-label=\"settings\"\n onClick={handleToggleFilters}\n >\n <FilterListIcon />\n </IconButton>\n <Typography variant=\"h6\">\n Filters ({numberOfSelectedFilters ? numberOfSelectedFilters : 0})\n </Typography>\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n makeStyles,\n Typography,\n Divider,\n Card,\n CardHeader,\n Button,\n CardContent,\n Select,\n Checkbox,\n List,\n ListItem,\n ListItemText,\n MenuItem,\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n background: 'transparent',\n boxShadow: '0px 0px 0px 0px',\n },\n checkbox: {\n padding: theme.spacing(0, 1, 0, 1),\n },\n dropdown: {\n width: '100%',\n },\n}));\n\nexport type FiltersState = {\n selected: string;\n checked: Array<string>;\n};\n\nexport type FilterOptions = {\n kind: Array<string>;\n lifecycle: Array<string>;\n};\n\ntype FiltersProps = {\n filters: FiltersState;\n filterOptions: FilterOptions;\n resetFilters: () => void;\n updateSelected: (filter: string) => void;\n updateChecked: (filter: string) => void;\n};\n\nexport const Filters = ({\n filters,\n filterOptions,\n resetFilters,\n updateSelected,\n updateChecked,\n}: FiltersProps) => {\n const classes = useStyles();\n\n return (\n <Card className={classes.filters}>\n <CardHeader\n title={<Typography variant=\"h6\">Filters</Typography>}\n action={\n <Button color=\"primary\" onClick={() => resetFilters()}>\n CLEAR ALL\n </Button>\n }\n />\n <Divider />\n {filterOptions.kind.length === 0 && filterOptions.lifecycle.length === 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">\n Filters cannot be applied to available results\n </Typography>\n </CardContent>\n )}\n {filterOptions.kind.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Kind</Typography>\n <Select\n id=\"outlined-select\"\n onChange={(e: React.ChangeEvent<any>) =>\n updateSelected(e?.target?.value)\n }\n variant=\"outlined\"\n className={classes.dropdown}\n value={filters.selected}\n >\n {filterOptions.kind.map(filter => (\n <MenuItem\n selected={filter === ''}\n dense\n key={filter}\n value={filter}\n >\n {filter}\n </MenuItem>\n ))}\n </Select>\n </CardContent>\n )}\n {filterOptions.lifecycle.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Lifecycle</Typography>\n <List disablePadding dense>\n {filterOptions.lifecycle.map(filter => (\n <ListItem\n key={filter}\n dense\n button\n onClick={() => updateChecked(filter)}\n >\n <Checkbox\n edge=\"start\"\n disableRipple\n className={classes.checkbox}\n color=\"primary\"\n checked={filters.checked.includes(filter)}\n tabIndex={-1}\n value={filter}\n name={filter}\n />\n <ListItemText id={filter} primary={filter} />\n </ListItem>\n ))}\n </List>\n </CardContent>\n )}\n </Card>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Divider, Grid, makeStyles, Typography } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect, useState } from 'react';\nimport { useAsync } from 'react-use';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\n\nimport { Filters, FiltersButton, FiltersState } from './Filters';\nimport { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';\n\nimport {\n EmptyState,\n Link,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype Result = {\n name: string;\n description: string | undefined;\n owner: string | undefined;\n kind: string;\n lifecycle: string | undefined;\n url: string;\n};\ntype SearchResults = Array<Result>;\n\nconst useStyles = makeStyles(theme => ({\n searchQuery: {\n color: theme.palette.text.primary,\n background: theme.palette.background.default,\n borderRadius: '10%',\n },\n tableHeader: {\n margin: theme.spacing(1, 0, 0, 0),\n display: 'flex',\n },\n divider: {\n width: '1px',\n margin: theme.spacing(0, 2),\n padding: theme.spacing(2, 0),\n },\n}));\n\ntype SearchResultProps = {\n searchQuery?: string;\n};\n\ntype TableHeaderProps = {\n searchQuery?: string;\n numberOfSelectedFilters: number;\n numberOfResults: number;\n handleToggleFilters: () => void;\n};\n\n// TODO: move out column to make the search result component more generic\nconst columns: TableColumn[] = [\n {\n title: 'Name',\n field: 'name',\n highlight: true,\n render: (result: Partial<Result>) => (\n <Link to={result.url || ''}>{result.name}</Link>\n ),\n },\n {\n title: 'Description',\n field: 'description',\n },\n {\n title: 'Owner',\n field: 'owner',\n },\n {\n title: 'Kind',\n field: 'kind',\n },\n {\n title: 'LifeCycle',\n field: 'lifecycle',\n },\n];\n\nconst TableHeader = ({\n searchQuery,\n numberOfSelectedFilters,\n numberOfResults,\n handleToggleFilters,\n}: TableHeaderProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.tableHeader}>\n <FiltersButton\n numberOfSelectedFilters={numberOfSelectedFilters}\n handleToggleFilters={handleToggleFilters}\n />\n <Divider className={classes.divider} orientation=\"vertical\" />\n <Grid item xs={12}>\n {searchQuery ? (\n <Typography variant=\"h6\">\n {`${numberOfResults} `}\n {numberOfResults > 1 ? `results for ` : `result for `}\n <span className={classes.searchQuery}>\"{searchQuery}\"</span>{' '}\n </Typography>\n ) : (\n <Typography variant=\"h6\">{`${numberOfResults} results`}</Typography>\n )}\n </Grid>\n </div>\n );\n};\n\nexport const SearchResult = ({ searchQuery }: SearchResultProps) => {\n const catalogApi = useApi(catalogApiRef);\n\n const [showFilters, toggleFilters] = useState(false);\n const [selectedFilters, setSelectedFilters] = useState<FiltersState>({\n selected: '',\n checked: [],\n });\n\n const [filteredResults, setFilteredResults] = useState<SearchResults>([]);\n\n const {\n loading,\n error,\n value: results,\n } = useAsync(async () => {\n const entities = await catalogApi.getEntities();\n return entities.items.map((entity: Entity) => ({\n name: entity.metadata.name,\n description: entity.metadata.description,\n owner:\n typeof entity.spec?.owner === 'string' ? entity.spec?.owner : undefined,\n kind: entity.kind,\n lifecycle:\n typeof entity.spec?.lifecycle === 'string'\n ? entity.spec?.lifecycle\n : undefined,\n url: `/catalog/${\n entity.metadata.namespace?.toLocaleLowerCase('en-US') ||\n ENTITY_DEFAULT_NAMESPACE\n }/${entity.kind.toLocaleLowerCase('en-US')}/${entity.metadata.name}`,\n }));\n }, []);\n\n useEffect(() => {\n if (results) {\n let withFilters = results;\n\n // apply filters\n\n // filter on selected\n if (selectedFilters.selected !== '') {\n withFilters = results.filter((result: Result) =>\n selectedFilters.selected.includes(result.kind),\n );\n }\n\n // filter on checked\n if (selectedFilters.checked.length > 0) {\n withFilters = withFilters.filter(\n (result: Result) =>\n result.lifecycle &&\n selectedFilters.checked.includes(result.lifecycle),\n );\n }\n\n // filter on searchQuery\n if (searchQuery) {\n withFilters = withFilters.filter(\n (result: Result) =>\n result.name?.toLocaleLowerCase('en-US').includes(searchQuery) ||\n result.name\n ?.toLocaleLowerCase('en-US')\n .includes(searchQuery.split(' ').join('-')) ||\n result.description\n ?.toLocaleLowerCase('en-US')\n .includes(searchQuery),\n );\n }\n\n setFilteredResults(withFilters);\n }\n }, [selectedFilters, searchQuery, results]);\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return (\n <Alert severity=\"error\">\n Error encountered while fetching search results. {error.toString()}\n </Alert>\n );\n }\n if (!results || results.length === 0) {\n return <EmptyState missing=\"data\" title=\"Sorry, no results were found\" />;\n }\n\n const resetFilters = () => {\n setSelectedFilters({\n selected: '',\n checked: [],\n });\n };\n\n const updateSelected = (filter: string) => {\n setSelectedFilters(prevState => ({\n ...prevState,\n selected: filter,\n }));\n };\n\n const updateChecked = (filter: string) => {\n if (selectedFilters.checked.includes(filter)) {\n setSelectedFilters(prevState => ({\n ...prevState,\n checked: prevState.checked.filter(item => item !== filter),\n }));\n return;\n }\n\n setSelectedFilters(prevState => ({\n ...prevState,\n checked: [...prevState.checked, filter],\n }));\n };\n\n const filterOptions = results.reduce(\n (acc, curr) => {\n if (curr.kind && acc.kind.indexOf(curr.kind) < 0) {\n acc.kind.push(curr.kind);\n }\n if (curr.lifecycle && acc.lifecycle.indexOf(curr.lifecycle) < 0) {\n acc.lifecycle.push(curr.lifecycle);\n }\n return acc;\n },\n {\n kind: [] as Array<string>,\n lifecycle: [] as Array<string>,\n },\n );\n\n return (\n <>\n <Grid container>\n {showFilters && (\n <Grid item xs={3}>\n <Filters\n filters={selectedFilters}\n filterOptions={filterOptions}\n resetFilters={resetFilters}\n updateSelected={updateSelected}\n updateChecked={updateChecked}\n />\n </Grid>\n )}\n <Grid item xs={showFilters ? 9 : 12}>\n <Table\n options={{ paging: true, pageSize: 20, search: false }}\n data={filteredResults}\n columns={columns}\n title={\n <TableHeader\n searchQuery={searchQuery}\n numberOfResults={filteredResults.length}\n numberOfSelectedFilters={\n (selectedFilters.selected !== '' ? 1 : 0) +\n selectedFilters.checked.length\n }\n handleToggleFilters={() => toggleFilters(!showFilters)}\n />\n }\n />\n </Grid>\n </Grid>\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Grid } from '@material-ui/core';\nimport React, { useEffect, useState } from 'react';\nimport { useDebounce } from 'react-use';\nimport { SearchBar } from './LegacySearchBar';\nimport { SearchResult } from './LegacySearchResult';\nimport {\n Content,\n Header,\n Page,\n useQueryParamState,\n} from '@backstage/core-components';\n\n/**\n * @deprecated This SearchPage, powered directly by the Catalog API, will be\n * removed from a future release of this plugin.\n */\nexport const LegacySearchPage = () => {\n const [queryString, setQueryString] = useQueryParamState<string>('query');\n const [searchQuery, setSearchQuery] = useState(queryString ?? '');\n\n const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {\n event.preventDefault();\n setSearchQuery(event.target.value);\n };\n\n useEffect(() => setSearchQuery(queryString ?? ''), [queryString]);\n\n useDebounce(\n () => {\n setQueryString(searchQuery);\n },\n 200,\n [searchQuery],\n );\n\n const handleClearSearchBar = () => {\n setSearchQuery('');\n };\n\n return (\n <Page themeId=\"home\">\n <Header title=\"Search\" />\n <Content>\n <Grid container direction=\"row\">\n <Grid item xs={12}>\n <SearchBar\n handleSearch={handleSearch}\n handleClearSearchBar={handleClearSearchBar}\n searchQuery={searchQuery}\n />\n </Grid>\n <Grid item xs={12}>\n <SearchResult\n searchQuery={(queryString ?? '').toLocaleLowerCase('en-US')}\n />\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect } from 'react';\nimport { usePrevious } from 'react-use';\nimport qs from 'qs';\nimport { useLocation, useOutlet } from 'react-router';\nimport { SearchContextProvider, useSearch } from '../SearchContext';\nimport { JsonObject } from '@backstage/types';\nimport { LegacySearchPage } from '../LegacySearchPage';\n\nexport const UrlUpdater = () => {\n const location = useLocation();\n const {\n term,\n setTerm,\n types,\n setTypes,\n pageCursor,\n setPageCursor,\n filters,\n setFilters,\n } = useSearch();\n\n const prevQueryParams = usePrevious(location.search);\n useEffect(() => {\n // Only respond to changes to url query params\n if (location.search === prevQueryParams) {\n return;\n }\n\n const query =\n qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {};\n\n if (query.filters) {\n setFilters(query.filters as JsonObject);\n }\n\n if (query.query) {\n setTerm(query.query as string);\n }\n\n if (query.pageCursor) {\n setPageCursor(query.pageCursor as string);\n }\n\n if (query.types) {\n setTypes(query.types as string[]);\n }\n }, [prevQueryParams, location, setTerm, setTypes, setPageCursor, setFilters]);\n\n useEffect(() => {\n const newParams = qs.stringify(\n {\n query: term,\n types,\n pageCursor,\n filters,\n },\n { arrayFormat: 'brackets' },\n );\n const newUrl = `${window.location.pathname}?${newParams}`;\n\n // We directly manipulate window history here in order to not re-render\n // infinitely (state => location => state => etc). The intention of this\n // code is just to ensure the right query/filters are loaded when a user\n // clicks the \"back\" button after clicking a result.\n window.history.replaceState(null, document.title, newUrl);\n }, [term, types, pageCursor, filters]);\n\n return null;\n};\n\nexport const SearchPage = () => {\n const outlet = useOutlet();\n\n return (\n <SearchContextProvider>\n <UrlUpdater />\n {outlet || <LegacySearchPage />}\n </SearchContextProvider>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button, makeStyles } from '@material-ui/core';\nimport ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';\nimport ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';\nimport React from 'react';\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n margin: theme.spacing(4),\n },\n}));\n\nexport const SearchResultPager = () => {\n const { fetchNextPage, fetchPreviousPage } = useSearch();\n const classes = useStyles();\n\n if (!fetchNextPage && !fetchPreviousPage) {\n return <></>;\n }\n\n return (\n <nav arial-label=\"pagination navigation\" className={classes.root}>\n <Button\n aria-label=\"previous page\"\n disabled={!fetchPreviousPage}\n onClick={fetchPreviousPage}\n startIcon={<ArrowBackIosIcon />}\n size=\"small\"\n >\n Back\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n size=\"small\"\n >\n Next\n </Button>\n </nav>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n Checkbox,\n Chip,\n FormControl,\n InputLabel,\n ListItemText,\n makeStyles,\n MenuItem,\n Select,\n} from '@material-ui/core';\nimport React, { ChangeEvent } from 'react';\nimport { useEffectOnce } from 'react-use';\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles(theme => ({\n label: {\n textTransform: 'capitalize',\n },\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n marginTop: theme.spacing(1),\n },\n chip: {\n margin: 2,\n },\n}));\n\nexport type SearchTypeProps = {\n className?: string;\n name: string;\n values?: string[];\n defaultValue?: string[] | string | null;\n};\n\nconst SearchType = ({\n values = [],\n className,\n name,\n defaultValue,\n}: SearchTypeProps) => {\n const classes = useStyles();\n const { types, setTypes } = useSearch();\n\n useEffectOnce(() => {\n if (!types.length) {\n if (defaultValue && Array.isArray(defaultValue)) {\n setTypes(defaultValue);\n } else if (defaultValue) {\n setTypes([defaultValue]);\n }\n }\n });\n\n const handleChange = (e: ChangeEvent<{ value: unknown }>) => {\n const value = e.target.value as string[];\n setTypes(value as string[]);\n };\n\n return (\n <FormControl\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-typefilter-next\"\n >\n <InputLabel className={classes.label} margin=\"dense\">\n {name}\n </InputLabel>\n <Select\n multiple\n variant=\"outlined\"\n value={types}\n onChange={handleChange}\n placeholder=\"All Results\"\n renderValue={selected => (\n <div className={classes.chips}>\n {(selected as string[]).map(value => (\n <Chip\n key={value}\n label={value}\n className={classes.chip}\n size=\"small\"\n />\n ))}\n </div>\n )}\n >\n {values.map((value: string) => (\n <MenuItem key={value} value={value}>\n <Checkbox checked={types.indexOf(value) > -1} />\n <ListItemText primary={value} />\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n\nexport { SearchType };\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SearchClient, searchApiRef } from './apis';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n createRoutableExtension,\n discoveryApiRef,\n createComponentExtension,\n identityApiRef,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n path: '/search',\n title: 'search',\n});\n\nexport const rootNextRouteRef = createRouteRef({\n path: '/search-next',\n title: 'search',\n});\n\nexport const searchPlugin = createPlugin({\n id: 'search',\n apis: [\n createApiFactory({\n api: searchApiRef,\n deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },\n factory: ({ discoveryApi, identityApi }) => {\n return new SearchClient({ discoveryApi, identityApi });\n },\n }),\n ],\n routes: {\n root: rootRouteRef,\n nextRoot: rootNextRouteRef,\n },\n});\n\nexport const SearchPage = searchPlugin.provide(\n createRoutableExtension({\n name: 'SearchPage',\n component: () => import('./components/SearchPage').then(m => m.SearchPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchPage /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchPageNext = searchPlugin.provide(\n createRoutableExtension({\n name: 'SearchPageNext',\n component: () => import('./components/SearchPage').then(m => m.SearchPage),\n mountPoint: rootNextRouteRef,\n }),\n);\n\nexport const SearchBar = searchPlugin.provide(\n createComponentExtension({\n name: 'SearchBar',\n component: {\n lazy: () => import('./components/SearchBar').then(m => m.SearchBar),\n },\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchBar /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchBarNext = searchPlugin.provide(\n createComponentExtension({\n name: 'SearchBarNext',\n component: {\n lazy: () => import('./components/SearchBar').then(m => m.SearchBar),\n },\n }),\n);\n\nexport const SearchResult = searchPlugin.provide(\n createComponentExtension({\n name: 'SearchResult',\n component: {\n lazy: () => import('./components/SearchResult').then(m => m.SearchResult),\n },\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchResult /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchResultNext = searchPlugin.provide(\n createComponentExtension({\n name: 'SearchResultNext',\n component: {\n lazy: () => import('./components/SearchResult').then(m => m.SearchResult),\n },\n }),\n);\n\nexport const DefaultResultListItem = searchPlugin.provide(\n createComponentExtension({\n name: 'DefaultResultListItem',\n component: {\n lazy: () =>\n import('./components/DefaultResultListItem').then(\n m => m.DefaultResultListItem,\n ),\n },\n }),\n);\n\nexport const HomePageSearchBar = searchPlugin.provide(\n createComponentExtension({\n name: 'HomePageSearchBar',\n component: {\n lazy: () =>\n import('./components/HomePageComponent').then(m => m.HomePageSearchBar),\n },\n }),\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport qs from 'qs';\nimport React, { useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { rootRouteRef } from '../../plugin';\n\nimport { SidebarSearchField } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nexport const SidebarSearch = () => {\n const searchRoute = useRouteRef(rootRouteRef);\n const navigate = useNavigate();\n const handleSearch = useCallback(\n (query: string): void => {\n const queryString = qs.stringify({ query }, { addQueryPrefix: true });\n\n navigate(`${searchRoute()}${queryString}`);\n },\n [navigate, searchRoute],\n );\n\n return <SidebarSearchField onSearch={handleSearch} to=\"/search\" />;\n};\n"],"names":["useStyles","FiltersButton","Filters","SearchBar","makeStyles","IconButton","InputBase","SearchResult","SearchPage"],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Progress, ResponseErrorPanel, EmptyState } from '@backstage/core-components';
|
|
2
2
|
import React from 'react';
|
|
3
|
-
import { u as useSearch } from './index-
|
|
3
|
+
import { u as useSearch } from './index-9c0d67e6.esm.js';
|
|
4
4
|
import '@backstage/core-plugin-api';
|
|
5
5
|
import '@backstage/errors';
|
|
6
6
|
import 'qs';
|
|
@@ -43,4 +43,4 @@ const SearchResultComponent = ({children}) => {
|
|
|
43
43
|
};
|
|
44
44
|
|
|
45
45
|
export { SearchResultComponent as SearchResult };
|
|
46
|
-
//# sourceMappingURL=index-
|
|
46
|
+
//# sourceMappingURL=index-ee8d2563.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-ee8d2563.esm.js","sources":["../../src/components/SearchResult/SearchResult.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n EmptyState,\n Progress,\n ResponseErrorPanel,\n} from '@backstage/core-components';\nimport { SearchResult } from '@backstage/search-common';\nimport React from 'react';\nimport { useSearch } from '../SearchContext';\n\ntype Props = {\n children: (results: { results: SearchResult[] }) => JSX.Element;\n};\n\nexport const SearchResultComponent = ({ children }: Props) => {\n const {\n result: { loading, error, value },\n } = useSearch();\n\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return (\n <ResponseErrorPanel\n title=\"Error encountered while fetching search results\"\n error={error}\n />\n );\n }\n\n if (!value?.results.length) {\n return <EmptyState missing=\"data\" title=\"Sorry, no results were found\" />;\n }\n\n return <>{children({ results: value.results })}</>;\n};\n\nexport { SearchResultComponent as SearchResult };\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;MA6Ba,wBAAwB,CAAC,CAAE,cAAsB;AAC5D,QAAM;AAAA,IACJ,QAAQ,CAAE,SAAS,OAAO;AAAA,MACxB;AAEJ,MAAI,SAAS;AACX,+CAAQ,UAAD;AAAA;AAET,MAAI,OAAO;AACT,+CACG,oBAAD;AAAA,MACE,OAAM;AAAA,MACN;AAAA;AAAA;AAKN,MAAI,iCAAQ,QAAQ,SAAQ;AAC1B,+CAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,MAAO,OAAM;AAAA;AAAA;AAG1C,mEAAU,SAAS,CAAE,SAAS,MAAM;AAAA;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
|
|
3
3
|
import * as _backstage_search_common from '@backstage/search-common';
|
|
4
4
|
import { SearchQuery, SearchResultSet } from '@backstage/search-common';
|
|
5
|
-
import { JsonObject } from '@backstage/
|
|
5
|
+
import { JsonObject } from '@backstage/types';
|
|
6
6
|
import React, { ReactElement } from 'react';
|
|
7
7
|
import { AsyncState } from 'react-use/lib/useAsync';
|
|
8
8
|
|
|
@@ -37,8 +37,9 @@ declare const Filters: ({ filters, filterOptions, resetFilters, updateSelected,
|
|
|
37
37
|
declare type Props$1 = {
|
|
38
38
|
className?: string;
|
|
39
39
|
debounceTime?: number;
|
|
40
|
+
placeholder?: string;
|
|
40
41
|
};
|
|
41
|
-
declare const SearchBar: ({ className, debounceTime }: Props$1) => JSX.Element;
|
|
42
|
+
declare const SearchBar: ({ className, debounceTime, placeholder, }: Props$1) => JSX.Element;
|
|
42
43
|
|
|
43
44
|
declare type SearchContextValue = {
|
|
44
45
|
result: AsyncState<SearchResultSet>;
|
|
@@ -118,9 +119,10 @@ declare const SearchPageNext: () => JSX.Element;
|
|
|
118
119
|
* <SearchBar /> component instead. This component will be removed in an
|
|
119
120
|
* upcoming release.
|
|
120
121
|
*/
|
|
121
|
-
declare const SearchBarNext: ({ className, debounceTime }: {
|
|
122
|
+
declare const SearchBarNext: ({ className, debounceTime, placeholder, }: {
|
|
122
123
|
className?: string | undefined;
|
|
123
124
|
debounceTime?: number | undefined;
|
|
125
|
+
placeholder?: string | undefined;
|
|
124
126
|
}) => JSX.Element;
|
|
125
127
|
declare const SearchResult: ({ children }: {
|
|
126
128
|
children: (results: {
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as DefaultResultListItem, F as Filters, c as FiltersButton, H as HomePageSearchBar, S as Router, a as SearchBar, j as SearchBarNext, d as SearchContextProvider, e as SearchFilter, f as SearchFilterNext, k as SearchPage, l as SearchPageNext, n as SearchResult, g as SearchResultPager, h as SearchType, i as SidebarSearch, m as plugin, s as searchApiRef, m as searchPlugin, u as useSearch } from './esm/index-
|
|
1
|
+
export { D as DefaultResultListItem, F as Filters, c as FiltersButton, H as HomePageSearchBar, S as Router, a as SearchBar, j as SearchBarNext, d as SearchContextProvider, e as SearchFilter, f as SearchFilterNext, k as SearchPage, l as SearchPageNext, n as SearchResult, g as SearchResultPager, h as SearchType, i as SidebarSearch, m as plugin, s as searchApiRef, m as searchPlugin, u as useSearch } from './esm/index-9c0d67e6.esm.js';
|
|
2
2
|
import 'react';
|
|
3
3
|
import '@material-ui/core';
|
|
4
4
|
import '@backstage/core-components';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/plugin-search",
|
|
3
3
|
"description": "The Backstage plugin that provides your backstage app with search",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.16",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -30,14 +30,15 @@
|
|
|
30
30
|
"clean": "backstage-cli clean"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@backstage/catalog-model": "^0.9.
|
|
34
|
-
"@backstage/config": "^0.1.
|
|
35
|
-
"@backstage/core-components": "^0.
|
|
36
|
-
"@backstage/core-plugin-api": "^0.1.
|
|
37
|
-
"@backstage/errors": "^0.1.
|
|
38
|
-
"@backstage/plugin-catalog-react": "^0.
|
|
39
|
-
"@backstage/search-common": "^0.2.
|
|
40
|
-
"@backstage/theme": "^0.2.
|
|
33
|
+
"@backstage/catalog-model": "^0.9.6",
|
|
34
|
+
"@backstage/config": "^0.1.11",
|
|
35
|
+
"@backstage/core-components": "^0.7.2",
|
|
36
|
+
"@backstage/core-plugin-api": "^0.1.12",
|
|
37
|
+
"@backstage/errors": "^0.1.4",
|
|
38
|
+
"@backstage/plugin-catalog-react": "^0.6.2",
|
|
39
|
+
"@backstage/search-common": "^0.2.1",
|
|
40
|
+
"@backstage/theme": "^0.2.12",
|
|
41
|
+
"@backstage/types": "^0.1.1",
|
|
41
42
|
"@material-ui/core": "^4.12.2",
|
|
42
43
|
"@material-ui/icons": "^4.9.1",
|
|
43
44
|
"@material-ui/lab": "4.0.0-alpha.57",
|
|
@@ -50,21 +51,21 @@
|
|
|
50
51
|
"react-use": "^17.2.4"
|
|
51
52
|
},
|
|
52
53
|
"devDependencies": {
|
|
53
|
-
"@backstage/cli": "^0.
|
|
54
|
-
"@backstage/core-app-api": "^0.1.
|
|
55
|
-
"@backstage/dev-utils": "^0.2.
|
|
56
|
-
"@backstage/test-utils": "^0.1.
|
|
54
|
+
"@backstage/cli": "^0.8.1",
|
|
55
|
+
"@backstage/core-app-api": "^0.1.19",
|
|
56
|
+
"@backstage/dev-utils": "^0.2.12",
|
|
57
|
+
"@backstage/test-utils": "^0.1.20",
|
|
57
58
|
"@testing-library/jest-dom": "^5.10.1",
|
|
58
59
|
"@testing-library/react": "^11.2.5",
|
|
59
|
-
"@testing-library/react-hooks": "^
|
|
60
|
+
"@testing-library/react-hooks": "^7.0.2",
|
|
60
61
|
"@testing-library/user-event": "^13.1.8",
|
|
61
62
|
"@types/jest": "^26.0.7",
|
|
62
63
|
"@types/node": "^14.14.32",
|
|
63
64
|
"cross-fetch": "^3.0.6",
|
|
64
|
-
"msw": "^0.
|
|
65
|
+
"msw": "^0.35.0"
|
|
65
66
|
},
|
|
66
67
|
"files": [
|
|
67
68
|
"dist"
|
|
68
69
|
],
|
|
69
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "3db0cb3683d3000666802af90a465ba4fb0d1e8d"
|
|
70
71
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-03e6e5c1.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-5da0411f.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-f5f6f3f0.esm.js","sources":["../../src/apis.ts","../../src/components/Filters/FiltersButton.tsx","../../src/components/Filters/Filters.tsx","../../src/components/SearchContext/SearchContext.tsx","../../src/components/SearchBar/SearchBar.tsx","../../src/components/SearchFilter/SearchFilter.tsx","../../src/components/LegacySearchPage/LegacySearchBar.tsx","../../src/components/LegacySearchPage/Filters/FiltersButton.tsx","../../src/components/LegacySearchPage/Filters/Filters.tsx","../../src/components/LegacySearchPage/LegacySearchResult.tsx","../../src/components/LegacySearchPage/LegacySearchPage.tsx","../../src/components/SearchPage/SearchPage.tsx","../../src/components/SearchResultPager/SearchResultPager.tsx","../../src/components/SearchType/SearchType.tsx","../../src/plugin.ts","../../src/components/SidebarSearch/SidebarSearch.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n createApiRef,\n DiscoveryApi,\n IdentityApi,\n} from '@backstage/core-plugin-api';\nimport { ResponseError } from '@backstage/errors';\nimport { SearchQuery, SearchResultSet } from '@backstage/search-common';\nimport qs from 'qs';\n\nexport const searchApiRef = createApiRef<SearchApi>({\n id: 'plugin.search.queryservice',\n description: 'Used to make requests against the search API',\n});\n\nexport interface SearchApi {\n query(query: SearchQuery): Promise<SearchResultSet>;\n}\n\nexport class SearchClient implements SearchApi {\n private readonly discoveryApi: DiscoveryApi;\n private readonly identityApi: IdentityApi;\n\n constructor(options: {\n discoveryApi: DiscoveryApi;\n identityApi: IdentityApi;\n }) {\n this.discoveryApi = options.discoveryApi;\n this.identityApi = options.identityApi;\n }\n\n async query(query: SearchQuery): Promise<SearchResultSet> {\n const token = await this.identityApi.getIdToken();\n const queryString = qs.stringify(query);\n const url = `${await this.discoveryApi.getBaseUrl(\n 'search/query',\n )}?${queryString}`;\n const response = await fetch(url, {\n headers: token ? { Authorization: `Bearer ${token}` } : {},\n });\n\n if (!response.ok) {\n throw await ResponseError.fromResponse(response);\n }\n\n return response.json();\n }\n}\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { makeStyles, IconButton, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n width: '250px',\n display: 'flex',\n },\n icon: {\n margin: theme.spacing(-1, 0, 0, 0),\n },\n}));\n\ntype FiltersButtonProps = {\n numberOfSelectedFilters: number;\n handleToggleFilters: () => void;\n};\n\nexport const FiltersButton = ({\n numberOfSelectedFilters,\n handleToggleFilters,\n}: FiltersButtonProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.filters}>\n <IconButton\n className={classes.icon}\n aria-label=\"settings\"\n onClick={handleToggleFilters}\n >\n <FilterListIcon />\n </IconButton>\n <Typography variant=\"h6\">\n Filters ({numberOfSelectedFilters ? numberOfSelectedFilters : 0})\n </Typography>\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n makeStyles,\n Typography,\n Divider,\n Card,\n CardHeader,\n Button,\n CardContent,\n Select,\n Checkbox,\n List,\n ListItem,\n ListItemText,\n MenuItem,\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n background: 'transparent',\n boxShadow: '0px 0px 0px 0px',\n },\n checkbox: {\n padding: theme.spacing(0, 1, 0, 1),\n },\n dropdown: {\n width: '100%',\n },\n}));\n\nexport type FiltersState = {\n selected: string;\n checked: Array<string>;\n};\n\nexport type FilterOptions = {\n kind: Array<string>;\n lifecycle: Array<string>;\n};\n\ntype FiltersProps = {\n filters: FiltersState;\n filterOptions: FilterOptions;\n resetFilters: () => void;\n updateSelected: (filter: string) => void;\n updateChecked: (filter: string) => void;\n};\n\nexport const Filters = ({\n filters,\n filterOptions,\n resetFilters,\n updateSelected,\n updateChecked,\n}: FiltersProps) => {\n const classes = useStyles();\n\n return (\n <Card className={classes.filters}>\n <CardHeader\n title={<Typography variant=\"h6\">Filters</Typography>}\n action={\n <Button color=\"primary\" onClick={() => resetFilters()}>\n CLEAR ALL\n </Button>\n }\n />\n <Divider />\n {filterOptions.kind.length === 0 && filterOptions.lifecycle.length === 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">\n Filters cannot be applied to available results\n </Typography>\n </CardContent>\n )}\n {filterOptions.kind.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Kind</Typography>\n <Select\n id=\"outlined-select\"\n onChange={(e: React.ChangeEvent<any>) =>\n updateSelected(e?.target?.value)\n }\n variant=\"outlined\"\n className={classes.dropdown}\n value={filters.selected}\n >\n {filterOptions.kind.map(filter => (\n <MenuItem\n selected={filter === ''}\n dense\n key={filter}\n value={filter}\n >\n {filter}\n </MenuItem>\n ))}\n </Select>\n </CardContent>\n )}\n {filterOptions.lifecycle.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Lifecycle</Typography>\n <List disablePadding dense>\n {filterOptions.lifecycle.map(filter => (\n <ListItem\n key={filter}\n dense\n button\n onClick={() => updateChecked(filter)}\n >\n <Checkbox\n edge=\"start\"\n disableRipple\n className={classes.checkbox}\n color=\"primary\"\n checked={filters.checked.includes(filter)}\n tabIndex={-1}\n value={filter}\n name={filter}\n />\n <ListItemText id={filter} primary={filter} />\n </ListItem>\n ))}\n </List>\n </CardContent>\n )}\n </Card>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { JsonObject } from '@backstage/config';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { SearchResultSet } from '@backstage/search-common';\nimport React, {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useState,\n} from 'react';\nimport { useAsync, usePrevious } from 'react-use';\nimport { AsyncState } from 'react-use/lib/useAsync';\nimport { searchApiRef } from '../../apis';\n\ntype SearchContextValue = {\n result: AsyncState<SearchResultSet>;\n term: string;\n setTerm: React.Dispatch<React.SetStateAction<string>>;\n types: string[];\n setTypes: React.Dispatch<React.SetStateAction<string[]>>;\n filters: JsonObject;\n setFilters: React.Dispatch<React.SetStateAction<JsonObject>>;\n pageCursor?: string;\n setPageCursor: React.Dispatch<React.SetStateAction<string | undefined>>;\n fetchNextPage?: React.DispatchWithoutAction;\n fetchPreviousPage?: React.DispatchWithoutAction;\n};\n\ntype SettableSearchContext = Omit<\n SearchContextValue,\n | 'result'\n | 'setTerm'\n | 'setTypes'\n | 'setFilters'\n | 'setPageCursor'\n | 'fetchNextPage'\n | 'fetchPreviousPage'\n>;\n\nexport const SearchContext = createContext<SearchContextValue | undefined>(\n undefined,\n);\n\nexport const SearchContextProvider = ({\n initialState = {\n term: '',\n pageCursor: undefined,\n filters: {},\n types: [],\n },\n children,\n}: PropsWithChildren<{ initialState?: SettableSearchContext }>) => {\n const searchApi = useApi(searchApiRef);\n const [pageCursor, setPageCursor] = useState<string | undefined>(\n initialState.pageCursor,\n );\n const [filters, setFilters] = useState<JsonObject>(initialState.filters);\n const [term, setTerm] = useState<string>(initialState.term);\n const [types, setTypes] = useState<string[]>(initialState.types);\n const prevTerm = usePrevious(term);\n\n const result = useAsync(\n () =>\n searchApi.query({\n term,\n filters,\n pageCursor: pageCursor,\n types,\n }),\n [term, filters, types, pageCursor],\n );\n\n const hasNextPage =\n !result.loading && !result.error && result.value?.nextPageCursor;\n const hasPreviousPage =\n !result.loading && !result.error && result.value?.previousPageCursor;\n const fetchNextPage = useCallback(() => {\n setPageCursor(result.value?.nextPageCursor);\n }, [result.value?.nextPageCursor]);\n const fetchPreviousPage = useCallback(() => {\n setPageCursor(result.value?.previousPageCursor);\n }, [result.value?.previousPageCursor]);\n\n useEffect(() => {\n // Any time a term is reset, we want to start from page 0.\n if (term && prevTerm && term !== prevTerm) {\n setPageCursor(undefined);\n }\n }, [term, prevTerm, initialState.pageCursor]);\n\n const value: SearchContextValue = {\n result,\n filters,\n setFilters,\n term,\n setTerm,\n types,\n setTypes,\n pageCursor,\n setPageCursor,\n fetchNextPage: hasNextPage ? fetchNextPage : undefined,\n fetchPreviousPage: hasPreviousPage ? fetchPreviousPage : undefined,\n };\n\n return <SearchContext.Provider value={value} children={children} />;\n};\n\nexport const useSearch = () => {\n const context = useContext(SearchContext);\n if (context === undefined) {\n throw new Error('useSearch must be used within a SearchContextProvider');\n }\n return context;\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, KeyboardEvent, useState } from 'react';\nimport { configApiRef, useApi } from '@backstage/core-plugin-api';\nimport { useDebounce } from 'react-use';\nimport { InputBase, InputAdornment, IconButton } from '@material-ui/core';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ClearButton from '@material-ui/icons/Clear';\n\nimport { useSearch } from '../SearchContext';\n\ntype PresenterProps = {\n value: string;\n onChange: (value: string) => void;\n onClear?: () => void;\n onSubmit?: () => void;\n className?: string;\n placeholder?: string;\n};\n\nexport const SearchBarBase = ({\n value,\n onChange,\n onSubmit,\n className,\n placeholder: overridePlaceholder,\n}: PresenterProps) => {\n const configApi = useApi(configApiRef);\n\n const onKeyDown = React.useCallback(\n (e: KeyboardEvent<HTMLInputElement>) => {\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onSubmit],\n );\n\n const handleClear = React.useCallback(() => {\n onChange('');\n }, [onChange]);\n\n const placeholder =\n overridePlaceholder ??\n `Search in ${configApi.getOptionalString('app.title') || 'Backstage'}`;\n\n return (\n <InputBase\n data-testid=\"search-bar-next\"\n fullWidth\n placeholder={placeholder}\n value={value}\n onChange={e => onChange(e.target.value)}\n inputProps={{ 'aria-label': 'Search' }}\n startAdornment={\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n }\n endAdornment={\n <InputAdornment position=\"end\">\n <IconButton aria-label=\"Clear\" onClick={handleClear}>\n <ClearButton />\n </IconButton>\n </InputAdornment>\n }\n {...(className && { className })}\n {...(onSubmit && { onKeyDown })}\n />\n );\n};\n\ntype Props = {\n className?: string;\n debounceTime?: number;\n};\n\nexport const SearchBar = ({ className, debounceTime = 0 }: Props) => {\n const { term, setTerm } = useSearch();\n const [value, setValue] = useState<string>(term);\n\n useEffect(() => {\n setValue(prevValue => (prevValue !== term ? term : prevValue));\n }, [term]);\n\n useDebounce(() => setTerm(value), debounceTime, [value]);\n\n const handleQuery = (newValue: string) => {\n setValue(newValue);\n };\n\n const handleClear = () => setValue('');\n\n return (\n <SearchBarBase\n className={className}\n value={value}\n onChange={handleQuery}\n onClear={handleClear}\n />\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { ReactElement, ChangeEvent, useEffect } from 'react';\nimport {\n makeStyles,\n FormControl,\n FormControlLabel,\n InputLabel,\n Checkbox,\n Select,\n MenuItem,\n FormLabel,\n} from '@material-ui/core';\n\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles({\n label: {\n textTransform: 'capitalize',\n },\n});\n\nexport type Component = {\n className?: string;\n name: string;\n values?: string[];\n defaultValue?: string[] | string | null;\n};\n\nexport type Props = Component & {\n component: (props: Component) => ReactElement;\n debug?: boolean;\n};\n\nconst CheckboxFilter = ({\n className,\n name,\n defaultValue,\n values = [],\n}: Component) => {\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n\n useEffect(() => {\n if (Array.isArray(defaultValue)) {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleChange = (e: ChangeEvent<HTMLInputElement>) => {\n const {\n target: { value, checked },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n const rest = ((filter as string[]) || []).filter(i => i !== value);\n const items = checked ? [...rest, value] : rest;\n return items.length ? { ...others, [name]: items } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n fullWidth\n data-testid=\"search-checkboxfilter-next\"\n >\n <FormLabel className={classes.label}>{name}</FormLabel>\n {values.map((value: string) => (\n <FormControlLabel\n key={value}\n control={\n <Checkbox\n color=\"primary\"\n tabIndex={-1}\n inputProps={{ 'aria-labelledby': value }}\n value={value}\n name={value}\n onChange={handleChange}\n checked={((filters[name] as string[]) ?? []).includes(value)}\n />\n }\n label={value}\n />\n ))}\n </FormControl>\n );\n};\n\nconst SelectFilter = ({\n className,\n name,\n defaultValue,\n values = [],\n}: Component) => {\n const classes = useStyles();\n const { filters, setFilters } = useSearch();\n\n useEffect(() => {\n if (typeof defaultValue === 'string') {\n setFilters(prevFilters => ({\n ...prevFilters,\n [name]: defaultValue,\n }));\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n const handleChange = (e: ChangeEvent<{ value: unknown }>) => {\n const {\n target: { value },\n } = e;\n\n setFilters(prevFilters => {\n const { [name]: filter, ...others } = prevFilters;\n return value ? { ...others, [name]: value as string } : others;\n });\n };\n\n return (\n <FormControl\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-selectfilter-next\"\n >\n <InputLabel className={classes.label} margin=\"dense\">\n {name}\n </InputLabel>\n <Select\n variant=\"outlined\"\n value={filters[name] || ''}\n onChange={handleChange}\n >\n <MenuItem value=\"\">\n <em>All</em>\n </MenuItem>\n {values.map((value: string) => (\n <MenuItem key={value} value={value}>\n {value}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n\nconst SearchFilter = ({ component: Element, ...props }: Props) => (\n <Element {...props} />\n);\n\nSearchFilter.Checkbox = (props: Omit<Props, 'component'> & Component) => (\n <SearchFilter {...props} component={CheckboxFilter} />\n);\n\nSearchFilter.Select = (props: Omit<Props, 'component'> & Component) => (\n <SearchFilter {...props} component={SelectFilter} />\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchFilter /> component instead. This component will be removed in an\n * upcoming release.\n */\nconst SearchFilterNext = SearchFilter;\n\nexport { SearchFilter, SearchFilterNext };\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { Paper } from '@material-ui/core';\nimport InputBase from '@material-ui/core/InputBase';\nimport IconButton from '@material-ui/core/IconButton';\nimport SearchIcon from '@material-ui/icons/Search';\nimport ClearButton from '@material-ui/icons/Clear';\n\nconst useStyles = makeStyles(() => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n },\n input: {\n flex: 1,\n },\n}));\n\ntype SearchBarProps = {\n searchQuery: string;\n handleSearch: any;\n handleClearSearchBar: any;\n};\n\nexport const SearchBar = ({\n searchQuery,\n handleSearch,\n handleClearSearchBar,\n}: SearchBarProps) => {\n const classes = useStyles();\n\n return (\n <Paper\n component=\"form\"\n onSubmit={e => handleSearch(e)}\n className={classes.root}\n >\n <IconButton disabled type=\"submit\" aria-label=\"search\">\n <SearchIcon />\n </IconButton>\n <InputBase\n className={classes.input}\n placeholder=\"Search in Backstage\"\n value={searchQuery}\n onChange={e => handleSearch(e)}\n inputProps={{ 'aria-label': 'search backstage' }}\n />\n <IconButton aria-label=\"search\" onClick={() => handleClearSearchBar()}>\n <ClearButton />\n </IconButton>\n </Paper>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { makeStyles, IconButton, Typography } from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n width: '250px',\n display: 'flex',\n },\n icon: {\n margin: theme.spacing(-1, 0, 0, 0),\n },\n}));\n\ntype FiltersButtonProps = {\n numberOfSelectedFilters: number;\n handleToggleFilters: () => void;\n};\n\nexport const FiltersButton = ({\n numberOfSelectedFilters,\n handleToggleFilters,\n}: FiltersButtonProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.filters}>\n <IconButton\n className={classes.icon}\n aria-label=\"settings\"\n onClick={handleToggleFilters}\n >\n <FilterListIcon />\n </IconButton>\n <Typography variant=\"h6\">\n Filters ({numberOfSelectedFilters ? numberOfSelectedFilters : 0})\n </Typography>\n </div>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n makeStyles,\n Typography,\n Divider,\n Card,\n CardHeader,\n Button,\n CardContent,\n Select,\n Checkbox,\n List,\n ListItem,\n ListItemText,\n MenuItem,\n} from '@material-ui/core';\n\nconst useStyles = makeStyles(theme => ({\n filters: {\n background: 'transparent',\n boxShadow: '0px 0px 0px 0px',\n },\n checkbox: {\n padding: theme.spacing(0, 1, 0, 1),\n },\n dropdown: {\n width: '100%',\n },\n}));\n\nexport type FiltersState = {\n selected: string;\n checked: Array<string>;\n};\n\nexport type FilterOptions = {\n kind: Array<string>;\n lifecycle: Array<string>;\n};\n\ntype FiltersProps = {\n filters: FiltersState;\n filterOptions: FilterOptions;\n resetFilters: () => void;\n updateSelected: (filter: string) => void;\n updateChecked: (filter: string) => void;\n};\n\nexport const Filters = ({\n filters,\n filterOptions,\n resetFilters,\n updateSelected,\n updateChecked,\n}: FiltersProps) => {\n const classes = useStyles();\n\n return (\n <Card className={classes.filters}>\n <CardHeader\n title={<Typography variant=\"h6\">Filters</Typography>}\n action={\n <Button color=\"primary\" onClick={() => resetFilters()}>\n CLEAR ALL\n </Button>\n }\n />\n <Divider />\n {filterOptions.kind.length === 0 && filterOptions.lifecycle.length === 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">\n Filters cannot be applied to available results\n </Typography>\n </CardContent>\n )}\n {filterOptions.kind.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Kind</Typography>\n <Select\n id=\"outlined-select\"\n onChange={(e: React.ChangeEvent<any>) =>\n updateSelected(e?.target?.value)\n }\n variant=\"outlined\"\n className={classes.dropdown}\n value={filters.selected}\n >\n {filterOptions.kind.map(filter => (\n <MenuItem\n selected={filter === ''}\n dense\n key={filter}\n value={filter}\n >\n {filter}\n </MenuItem>\n ))}\n </Select>\n </CardContent>\n )}\n {filterOptions.lifecycle.length > 0 && (\n <CardContent>\n <Typography variant=\"subtitle2\">Lifecycle</Typography>\n <List disablePadding dense>\n {filterOptions.lifecycle.map(filter => (\n <ListItem\n key={filter}\n dense\n button\n onClick={() => updateChecked(filter)}\n >\n <Checkbox\n edge=\"start\"\n disableRipple\n className={classes.checkbox}\n color=\"primary\"\n checked={filters.checked.includes(filter)}\n tabIndex={-1}\n value={filter}\n name={filter}\n />\n <ListItemText id={filter} primary={filter} />\n </ListItem>\n ))}\n </List>\n </CardContent>\n )}\n </Card>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Divider, Grid, makeStyles, Typography } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect, useState } from 'react';\nimport { useAsync } from 'react-use';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\n\nimport { Filters, FiltersButton, FiltersState } from './Filters';\nimport { Entity, ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';\n\nimport {\n EmptyState,\n Link,\n Progress,\n Table,\n TableColumn,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\ntype Result = {\n name: string;\n description: string | undefined;\n owner: string | undefined;\n kind: string;\n lifecycle: string | undefined;\n url: string;\n};\ntype SearchResults = Array<Result>;\n\nconst useStyles = makeStyles(theme => ({\n searchQuery: {\n color: theme.palette.text.primary,\n background: theme.palette.background.default,\n borderRadius: '10%',\n },\n tableHeader: {\n margin: theme.spacing(1, 0, 0, 0),\n display: 'flex',\n },\n divider: {\n width: '1px',\n margin: theme.spacing(0, 2),\n padding: theme.spacing(2, 0),\n },\n}));\n\ntype SearchResultProps = {\n searchQuery?: string;\n};\n\ntype TableHeaderProps = {\n searchQuery?: string;\n numberOfSelectedFilters: number;\n numberOfResults: number;\n handleToggleFilters: () => void;\n};\n\n// TODO: move out column to make the search result component more generic\nconst columns: TableColumn[] = [\n {\n title: 'Name',\n field: 'name',\n highlight: true,\n render: (result: Partial<Result>) => (\n <Link to={result.url || ''}>{result.name}</Link>\n ),\n },\n {\n title: 'Description',\n field: 'description',\n },\n {\n title: 'Owner',\n field: 'owner',\n },\n {\n title: 'Kind',\n field: 'kind',\n },\n {\n title: 'LifeCycle',\n field: 'lifecycle',\n },\n];\n\nconst TableHeader = ({\n searchQuery,\n numberOfSelectedFilters,\n numberOfResults,\n handleToggleFilters,\n}: TableHeaderProps) => {\n const classes = useStyles();\n\n return (\n <div className={classes.tableHeader}>\n <FiltersButton\n numberOfSelectedFilters={numberOfSelectedFilters}\n handleToggleFilters={handleToggleFilters}\n />\n <Divider className={classes.divider} orientation=\"vertical\" />\n <Grid item xs={12}>\n {searchQuery ? (\n <Typography variant=\"h6\">\n {`${numberOfResults} `}\n {numberOfResults > 1 ? `results for ` : `result for `}\n <span className={classes.searchQuery}>\"{searchQuery}\"</span>{' '}\n </Typography>\n ) : (\n <Typography variant=\"h6\">{`${numberOfResults} results`}</Typography>\n )}\n </Grid>\n </div>\n );\n};\n\nexport const SearchResult = ({ searchQuery }: SearchResultProps) => {\n const catalogApi = useApi(catalogApiRef);\n\n const [showFilters, toggleFilters] = useState(false);\n const [selectedFilters, setSelectedFilters] = useState<FiltersState>({\n selected: '',\n checked: [],\n });\n\n const [filteredResults, setFilteredResults] = useState<SearchResults>([]);\n\n const {\n loading,\n error,\n value: results,\n } = useAsync(async () => {\n const entities = await catalogApi.getEntities();\n return entities.items.map((entity: Entity) => ({\n name: entity.metadata.name,\n description: entity.metadata.description,\n owner:\n typeof entity.spec?.owner === 'string' ? entity.spec?.owner : undefined,\n kind: entity.kind,\n lifecycle:\n typeof entity.spec?.lifecycle === 'string'\n ? entity.spec?.lifecycle\n : undefined,\n url: `/catalog/${\n entity.metadata.namespace?.toLowerCase() || ENTITY_DEFAULT_NAMESPACE\n }/${entity.kind.toLowerCase()}/${entity.metadata.name}`,\n }));\n }, []);\n\n useEffect(() => {\n if (results) {\n let withFilters = results;\n\n // apply filters\n\n // filter on selected\n if (selectedFilters.selected !== '') {\n withFilters = results.filter((result: Result) =>\n selectedFilters.selected.includes(result.kind),\n );\n }\n\n // filter on checked\n if (selectedFilters.checked.length > 0) {\n withFilters = withFilters.filter(\n (result: Result) =>\n result.lifecycle &&\n selectedFilters.checked.includes(result.lifecycle),\n );\n }\n\n // filter on searchQuery\n if (searchQuery) {\n withFilters = withFilters.filter(\n (result: Result) =>\n result.name?.toLocaleLowerCase('en-US').includes(searchQuery) ||\n result.name\n ?.toLocaleLowerCase('en-US')\n .includes(searchQuery.split(' ').join('-')) ||\n result.description\n ?.toLocaleLowerCase('en-US')\n .includes(searchQuery),\n );\n }\n\n setFilteredResults(withFilters);\n }\n }, [selectedFilters, searchQuery, results]);\n if (loading) {\n return <Progress />;\n }\n if (error) {\n return (\n <Alert severity=\"error\">\n Error encountered while fetching search results. {error.toString()}\n </Alert>\n );\n }\n if (!results || results.length === 0) {\n return <EmptyState missing=\"data\" title=\"Sorry, no results were found\" />;\n }\n\n const resetFilters = () => {\n setSelectedFilters({\n selected: '',\n checked: [],\n });\n };\n\n const updateSelected = (filter: string) => {\n setSelectedFilters(prevState => ({\n ...prevState,\n selected: filter,\n }));\n };\n\n const updateChecked = (filter: string) => {\n if (selectedFilters.checked.includes(filter)) {\n setSelectedFilters(prevState => ({\n ...prevState,\n checked: prevState.checked.filter(item => item !== filter),\n }));\n return;\n }\n\n setSelectedFilters(prevState => ({\n ...prevState,\n checked: [...prevState.checked, filter],\n }));\n };\n\n const filterOptions = results.reduce(\n (acc, curr) => {\n if (curr.kind && acc.kind.indexOf(curr.kind) < 0) {\n acc.kind.push(curr.kind);\n }\n if (curr.lifecycle && acc.lifecycle.indexOf(curr.lifecycle) < 0) {\n acc.lifecycle.push(curr.lifecycle);\n }\n return acc;\n },\n {\n kind: [] as Array<string>,\n lifecycle: [] as Array<string>,\n },\n );\n\n return (\n <>\n <Grid container>\n {showFilters && (\n <Grid item xs={3}>\n <Filters\n filters={selectedFilters}\n filterOptions={filterOptions}\n resetFilters={resetFilters}\n updateSelected={updateSelected}\n updateChecked={updateChecked}\n />\n </Grid>\n )}\n <Grid item xs={showFilters ? 9 : 12}>\n <Table\n options={{ paging: true, pageSize: 20, search: false }}\n data={filteredResults}\n columns={columns}\n title={\n <TableHeader\n searchQuery={searchQuery}\n numberOfResults={filteredResults.length}\n numberOfSelectedFilters={\n (selectedFilters.selected !== '' ? 1 : 0) +\n selectedFilters.checked.length\n }\n handleToggleFilters={() => toggleFilters(!showFilters)}\n />\n }\n />\n </Grid>\n </Grid>\n </>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { Grid } from '@material-ui/core';\nimport React, { useEffect, useState } from 'react';\nimport { useDebounce } from 'react-use';\nimport { SearchBar } from './LegacySearchBar';\nimport { SearchResult } from './LegacySearchResult';\nimport {\n Content,\n Header,\n Page,\n useQueryParamState,\n} from '@backstage/core-components';\n\n/**\n * @deprecated This SearchPage, powered directly by the Catalog API, will be\n * removed from a future release of this plugin.\n */\nexport const LegacySearchPage = () => {\n const [queryString, setQueryString] = useQueryParamState<string>('query');\n const [searchQuery, setSearchQuery] = useState(queryString ?? '');\n\n const handleSearch = (event: React.ChangeEvent<HTMLInputElement>) => {\n event.preventDefault();\n setSearchQuery(event.target.value);\n };\n\n useEffect(() => setSearchQuery(queryString ?? ''), [queryString]);\n\n useDebounce(\n () => {\n setQueryString(searchQuery);\n },\n 200,\n [searchQuery],\n );\n\n const handleClearSearchBar = () => {\n setSearchQuery('');\n };\n\n return (\n <Page themeId=\"home\">\n <Header title=\"Search\" />\n <Content>\n <Grid container direction=\"row\">\n <Grid item xs={12}>\n <SearchBar\n handleSearch={handleSearch}\n handleClearSearchBar={handleClearSearchBar}\n searchQuery={searchQuery}\n />\n </Grid>\n <Grid item xs={12}>\n <SearchResult\n searchQuery={(queryString ?? '').toLocaleLowerCase('en-US')}\n />\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect } from 'react';\nimport { usePrevious } from 'react-use';\nimport qs from 'qs';\nimport { useLocation, useOutlet } from 'react-router';\nimport { SearchContextProvider, useSearch } from '../SearchContext';\nimport { JsonObject } from '@backstage/config';\nimport { LegacySearchPage } from '../LegacySearchPage';\n\nexport const UrlUpdater = () => {\n const location = useLocation();\n const {\n term,\n setTerm,\n types,\n setTypes,\n pageCursor,\n setPageCursor,\n filters,\n setFilters,\n } = useSearch();\n\n const prevQueryParams = usePrevious(location.search);\n useEffect(() => {\n // Only respond to changes to url query params\n if (location.search === prevQueryParams) {\n return;\n }\n\n const query =\n qs.parse(location.search.substring(1), { arrayLimit: 0 }) || {};\n\n if (query.filters) {\n setFilters(query.filters as JsonObject);\n }\n\n if (query.query) {\n setTerm(query.query as string);\n }\n\n if (query.pageCursor) {\n setPageCursor(query.pageCursor as string);\n }\n\n if (query.types) {\n setTypes(query.types as string[]);\n }\n }, [prevQueryParams, location, setTerm, setTypes, setPageCursor, setFilters]);\n\n useEffect(() => {\n const newParams = qs.stringify(\n {\n query: term,\n types,\n pageCursor,\n filters,\n },\n { arrayFormat: 'brackets' },\n );\n const newUrl = `${window.location.pathname}?${newParams}`;\n\n // We directly manipulate window history here in order to not re-render\n // infinitely (state => location => state => etc). The intention of this\n // code is just to ensure the right query/filters are loaded when a user\n // clicks the \"back\" button after clicking a result.\n window.history.replaceState(null, document.title, newUrl);\n }, [term, types, pageCursor, filters]);\n\n return null;\n};\n\nexport const SearchPage = () => {\n const outlet = useOutlet();\n\n return (\n <SearchContextProvider>\n <UrlUpdater />\n {outlet || <LegacySearchPage />}\n </SearchContextProvider>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Button, makeStyles } from '@material-ui/core';\nimport ArrowBackIosIcon from '@material-ui/icons/ArrowBackIos';\nimport ArrowForwardIosIcon from '@material-ui/icons/ArrowForwardIos';\nimport React from 'react';\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles(theme => ({\n root: {\n display: 'flex',\n justifyContent: 'space-between',\n gap: theme.spacing(2),\n margin: theme.spacing(4),\n },\n}));\n\nexport const SearchResultPager = () => {\n const { fetchNextPage, fetchPreviousPage } = useSearch();\n const classes = useStyles();\n\n if (!fetchNextPage && !fetchPreviousPage) {\n return <></>;\n }\n\n return (\n <nav arial-label=\"pagination navigation\" className={classes.root}>\n <Button\n aria-label=\"previous page\"\n disabled={!fetchPreviousPage}\n onClick={fetchPreviousPage}\n startIcon={<ArrowBackIosIcon />}\n size=\"small\"\n >\n Back\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n size=\"small\"\n >\n Next\n </Button>\n </nav>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n Checkbox,\n Chip,\n FormControl,\n InputLabel,\n ListItemText,\n makeStyles,\n MenuItem,\n Select,\n} from '@material-ui/core';\nimport React, { ChangeEvent } from 'react';\nimport { useEffectOnce } from 'react-use';\nimport { useSearch } from '../SearchContext';\n\nconst useStyles = makeStyles(theme => ({\n label: {\n textTransform: 'capitalize',\n },\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n marginTop: theme.spacing(1),\n },\n chip: {\n margin: 2,\n },\n}));\n\nexport type SearchTypeProps = {\n className?: string;\n name: string;\n values?: string[];\n defaultValue?: string[] | string | null;\n};\n\nconst SearchType = ({\n values = [],\n className,\n name,\n defaultValue,\n}: SearchTypeProps) => {\n const classes = useStyles();\n const { types, setTypes } = useSearch();\n\n useEffectOnce(() => {\n if (!types.length) {\n if (defaultValue && Array.isArray(defaultValue)) {\n setTypes(defaultValue);\n } else if (defaultValue) {\n setTypes([defaultValue]);\n }\n }\n });\n\n const handleChange = (e: ChangeEvent<{ value: unknown }>) => {\n const value = e.target.value as string[];\n setTypes(value as string[]);\n };\n\n return (\n <FormControl\n className={className}\n variant=\"filled\"\n fullWidth\n data-testid=\"search-typefilter-next\"\n >\n <InputLabel className={classes.label} margin=\"dense\">\n {name}\n </InputLabel>\n <Select\n multiple\n variant=\"outlined\"\n value={types}\n onChange={handleChange}\n placeholder=\"All Results\"\n renderValue={selected => (\n <div className={classes.chips}>\n {(selected as string[]).map(value => (\n <Chip\n key={value}\n label={value}\n className={classes.chip}\n size=\"small\"\n />\n ))}\n </div>\n )}\n >\n {values.map((value: string) => (\n <MenuItem key={value} value={value}>\n <Checkbox checked={types.indexOf(value) > -1} />\n <ListItemText primary={value} />\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n );\n};\n\nexport { SearchType };\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { SearchClient, searchApiRef } from './apis';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n createRoutableExtension,\n discoveryApiRef,\n createComponentExtension,\n identityApiRef,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({\n path: '/search',\n title: 'search',\n});\n\nexport const rootNextRouteRef = createRouteRef({\n path: '/search-next',\n title: 'search',\n});\n\nexport const searchPlugin = createPlugin({\n id: 'search',\n apis: [\n createApiFactory({\n api: searchApiRef,\n deps: { discoveryApi: discoveryApiRef, identityApi: identityApiRef },\n factory: ({ discoveryApi, identityApi }) => {\n return new SearchClient({ discoveryApi, identityApi });\n },\n }),\n ],\n routes: {\n root: rootRouteRef,\n nextRoot: rootNextRouteRef,\n },\n});\n\nexport const SearchPage = searchPlugin.provide(\n createRoutableExtension({\n component: () => import('./components/SearchPage').then(m => m.SearchPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchPage /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchPageNext = searchPlugin.provide(\n createRoutableExtension({\n component: () => import('./components/SearchPage').then(m => m.SearchPage),\n mountPoint: rootNextRouteRef,\n }),\n);\n\nexport const SearchBar = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () => import('./components/SearchBar').then(m => m.SearchBar),\n },\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchBar /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchBarNext = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () => import('./components/SearchBar').then(m => m.SearchBar),\n },\n }),\n);\n\nexport const SearchResult = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () => import('./components/SearchResult').then(m => m.SearchResult),\n },\n }),\n);\n\n/**\n * @deprecated This component was used for rapid prototyping of the Backstage\n * Search platform. Now that the API has stabilized, you should use the\n * <SearchResult /> component instead. This component will be removed in an\n * upcoming release.\n */\nexport const SearchResultNext = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () => import('./components/SearchResult').then(m => m.SearchResult),\n },\n }),\n);\n\nexport const DefaultResultListItem = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () =>\n import('./components/DefaultResultListItem').then(\n m => m.DefaultResultListItem,\n ),\n },\n }),\n);\n\nexport const HomePageSearchBar = searchPlugin.provide(\n createComponentExtension({\n component: {\n lazy: () =>\n import('./components/HomePageComponent').then(m => m.HomePageSearchBar),\n },\n }),\n);\n","/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport qs from 'qs';\nimport React, { useCallback } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { rootRouteRef } from '../../plugin';\n\nimport { SidebarSearchField } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nexport const SidebarSearch = () => {\n const searchRoute = useRouteRef(rootRouteRef);\n const navigate = useNavigate();\n const handleSearch = useCallback(\n (query: string): void => {\n const queryString = qs.stringify({ query }, { addQueryPrefix: true });\n\n navigate(`${searchRoute()}${queryString}`);\n },\n [navigate, searchRoute],\n );\n\n return <SidebarSearchField onSearch={handleSearch} to=\"/search\" />;\n};\n"],"names":["useStyles","FiltersButton","Filters","SearchBar","makeStyles","IconButton","InputBase","SearchResult","SearchPage"],"mappings":";;;;;;;;;;;;;;;;;;;;;MAyBa,eAAe,aAAwB;AAAA,EAClD,IAAI;AAAA,EACJ,aAAa;AAAA;mBAOgC;AAAA,EAI7C,YAAY,SAGT;AACD,SAAK,eAAe,QAAQ;AAC5B,SAAK,cAAc,QAAQ;AAAA;AAAA,QAGvB,MAAM,OAA8C;AACxD,UAAM,QAAQ,MAAM,KAAK,YAAY;AACrC,UAAM,cAAc,GAAG,UAAU;AACjC,UAAM,MAAM,GAAG,MAAM,KAAK,aAAa,WACrC,mBACG;AACL,UAAM,WAAW,MAAM,MAAM,KAAK;AAAA,MAChC,SAAS,QAAQ,CAAE,eAAe,UAAU,WAAY;AAAA;AAG1D,QAAI,CAAC,SAAS,IAAI;AAChB,YAAM,MAAM,cAAc,aAAa;AAAA;AAGzC,WAAO,SAAS;AAAA;AAAA;;ACxCpB,MAAMA,cAAY,WAAW;AAAU,EACrC,SAAS;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA;AAAA,EAEX,MAAM;AAAA,IACJ,QAAQ,MAAM,QAAQ,IAAI,GAAG,GAAG;AAAA;AAAA;MASvBC,kBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,MACwB;AACxB,QAAM,UAAUD;AAEhB,6CACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,yCACrB,YAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,cAAW;AAAA,IACX,SAAS;AAAA,yCAER,gBAAD,4CAED,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAK,aACb,0BAA0B,0BAA0B,GAAE;AAAA;;AClBxE,MAAMA,cAAY,WAAW;AAAU,EACrC,SAAS;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS,MAAM,QAAQ,GAAG,GAAG,GAAG;AAAA;AAAA,EAElC,UAAU;AAAA,IACR,OAAO;AAAA;AAAA;MAsBEE,YAAU,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,MACkB;AAClB,QAAM,UAAUF;AAEhB,6CACG,MAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,yCACtB,YAAD;AAAA,IACE,2CAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,OAAK;AAAA,IAChC,4CACG,QAAD;AAAA,MAAQ,OAAM;AAAA,MAAU,SAAS,MAAM;AAAA,OAAgB;AAAA,0CAK1D,SAAD,OACC,cAAc,KAAK,WAAW,KAAK,cAAc,UAAU,WAAW,yCACpE,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,oDAKnC,cAAc,KAAK,SAAS,yCAC1B,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,6CAC/B,QAAD;AAAA,IACE,IAAG;AAAA,IACH,UAAU,CAAC,MAA2B;AAhGlD;AAiGc,4BAAe,6BAAG,WAAH,mBAAW;AAAA;AAAA,IAE5B,SAAQ;AAAA,IACR,WAAW,QAAQ;AAAA,IACnB,OAAO,QAAQ;AAAA,KAEd,cAAc,KAAK,IAAI,gDACrB,UAAD;AAAA,IACE,UAAU,WAAW;AAAA,IACrB,OAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,KAEN,YAMV,cAAc,UAAU,SAAS,yCAC/B,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,kDAC/B,MAAD;AAAA,IAAM,gBAAc;AAAA,IAAC,OAAK;AAAA,KACvB,cAAc,UAAU,IAAI,gDAC1B,UAAD;AAAA,IACE,KAAK;AAAA,IACL,OAAK;AAAA,IACL,QAAM;AAAA,IACN,SAAS,MAAM,cAAc;AAAA,yCAE5B,UAAD;AAAA,IACE,MAAK;AAAA,IACL,eAAa;AAAA,IACb,WAAW,QAAQ;AAAA,IACnB,OAAM;AAAA,IACN,SAAS,QAAQ,QAAQ,SAAS;AAAA,IAClC,UAAU;AAAA,IACV,OAAO;AAAA,IACP,MAAM;AAAA,0CAEP,cAAD;AAAA,IAAc,IAAI;AAAA,IAAQ,SAAS;AAAA;AAAA;;MCjFtC,gBAAgB,cAC3B;MAGW,wBAAwB,CAAC;AAAA,EACpC,eAAe;AAAA,IACb,MAAM;AAAA,IACN,YAAY;AAAA,IACZ,SAAS;AAAA,IACT,OAAO;AAAA;AAAA,EAET;AAAA,MACiE;AApEnE;AAqEE,QAAM,YAAY,OAAO;AACzB,QAAM,CAAC,YAAY,iBAAiB,SAClC,aAAa;AAEf,QAAM,CAAC,SAAS,cAAc,SAAqB,aAAa;AAChE,QAAM,CAAC,MAAM,WAAW,SAAiB,aAAa;AACtD,QAAM,CAAC,OAAO,YAAY,SAAmB,aAAa;AAC1D,QAAM,WAAW,YAAY;AAE7B,QAAM,SAAS,SACb,MACE,UAAU,MAAM;AAAA,IACd;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MAEJ,CAAC,MAAM,SAAS,OAAO;AAGzB,QAAM,cACJ,CAAC,OAAO,WAAW,CAAC,OAAO,uBAAgB,UAAP,mBAAc;AACpD,QAAM,kBACJ,CAAC,OAAO,WAAW,CAAC,OAAO,uBAAgB,UAAP,mBAAc;AACpD,QAAM,gBAAgB,YAAY,MAAM;AA7F1C;AA8FI,kBAAc,cAAO,UAAP,oBAAc;AAAA,KAC3B,CAAC,aAAO,UAAP,mBAAc;AAClB,QAAM,oBAAoB,YAAY,MAAM;AAhG9C;AAiGI,kBAAc,cAAO,UAAP,oBAAc;AAAA,KAC3B,CAAC,aAAO,UAAP,mBAAc;AAElB,YAAU,MAAM;AAEd,QAAI,QAAQ,YAAY,SAAS,UAAU;AACzC,oBAAc;AAAA;AAAA,KAEf,CAAC,MAAM,UAAU,aAAa;AAEjC,QAAM,QAA4B;AAAA,IAChC;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe,cAAc,gBAAgB;AAAA,IAC7C,mBAAmB,kBAAkB,oBAAoB;AAAA;AAG3D,6CAAQ,cAAc,UAAf;AAAA,IAAwB;AAAA,IAAc;AAAA;AAAA;MAGlC,YAAY,MAAM;AAC7B,QAAM,UAAU,WAAW;AAC3B,MAAI,YAAY,QAAW;AACzB,UAAM,IAAI,MAAM;AAAA;AAElB,SAAO;AAAA;;MC/FI,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,aAAa;AAAA,MACO;AACpB,QAAM,YAAY,OAAO;AAEzB,QAAM,YAAY,MAAM,YACtB,CAAC,MAAuC;AACtC,QAAI,YAAY,EAAE,QAAQ,SAAS;AACjC;AAAA;AAAA,KAGJ,CAAC;AAGH,QAAM,cAAc,MAAM,YAAY,MAAM;AAC1C,aAAS;AAAA,KACR,CAAC;AAEJ,QAAM,cACJ,oDACA,aAAa,UAAU,kBAAkB,gBAAgB;AAE3D,6CACG,WAAD;AAAA,IACE,eAAY;AAAA,IACZ,WAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA,UAAU,OAAK,SAAS,EAAE,OAAO;AAAA,IACjC,YAAY,CAAE,cAAc;AAAA,IAC5B,oDACG,gBAAD;AAAA,MAAgB,UAAS;AAAA,2CACtB,YAAD;AAAA,MAAY,cAAW;AAAA,MAAQ,UAAQ;AAAA,2CACpC,YAAD;AAAA,IAIN,kDACG,gBAAD;AAAA,MAAgB,UAAS;AAAA,2CACtB,YAAD;AAAA,MAAY,cAAW;AAAA,MAAQ,SAAS;AAAA,2CACrC,aAAD;AAAA,OAID,aAAa,CAAE;AAAA,OACf,YAAY,CAAE;AAAA;AAAA;MAUZG,cAAY,CAAC,CAAE,WAAW,eAAe,OAAe;AACnE,QAAM,CAAE,MAAM,WAAY;AAC1B,QAAM,CAAC,OAAO,YAAY,SAAiB;AAE3C,YAAU,MAAM;AACd,aAAS,eAAc,cAAc,OAAO,OAAO;AAAA,KAClD,CAAC;AAEJ,cAAY,MAAM,QAAQ,QAAQ,cAAc,CAAC;AAEjD,QAAM,cAAc,CAAC,aAAqB;AACxC,aAAS;AAAA;AAGX,QAAM,cAAc,MAAM,SAAS;AAEnC,6CACG,eAAD;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA;AAAA;;ACpFf,MAAMH,cAAY,WAAW;AAAA,EAC3B,OAAO;AAAA,IACL,eAAe;AAAA;AAAA;AAgBnB,MAAM,iBAAiB,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,MACM;AACf,QAAM,UAAUA;AAChB,QAAM,CAAE,SAAS,cAAe;AAEhC,YAAU,MAAM;AACd,QAAI,MAAM,QAAQ,eAAe;AAC/B,iBAAW;AAAgB,WACtB;AAAA,SACF,OAAO;AAAA;AAAA;AAAA,KAIX;AAEH,QAAM,eAAe,CAAC,MAAqC;AACzD,UAAM;AAAA,MACJ,QAAQ,CAAE,OAAO;AAAA,QACf;AAEJ,eAAW,iBAAe;AACxB,YAAM,EAAG,OAAO,WAAW,UAAW;AACtC,YAAM,OAAS,WAAuB,IAAI,OAAO,OAAK,MAAM;AAC5D,YAAM,QAAQ,UAAU,CAAC,GAAG,MAAM,SAAS;AAC3C,aAAO,MAAM,SAAS,IAAK,SAAS,OAAO,SAAU;AAAA;AAAA;AAIzD,6CACG,aAAD;AAAA,IACE;AAAA,IACA,WAAS;AAAA,IACT,eAAY;AAAA,yCAEX,WAAD;AAAA,IAAW,WAAW,QAAQ;AAAA,KAAQ,OACrC,OAAO,IAAI,CAAC,UAAe;AAvFlC;AAwFQ,+CAAC,kBAAD;AAAA,MACE,KAAK;AAAA,MACL,6CACG,UAAD;AAAA,QACE,OAAM;AAAA,QACN,UAAU;AAAA,QACV,YAAY,CAAE,mBAAmB;AAAA,QACjC;AAAA,QACA,MAAM;AAAA,QACN,UAAU;AAAA,QACV,SAAW,eAAQ,UAAR,YAA8B,IAAI,SAAS;AAAA;AAAA,MAG1D,OAAO;AAAA;AAAA;AAAA;AAOjB,MAAM,eAAe,CAAC;AAAA,EACpB;AAAA,EACA;AAAA,EACA;AAAA,EACA,SAAS;AAAA,MACM;AACf,QAAM,UAAUA;AAChB,QAAM,CAAE,SAAS,cAAe;AAEhC,YAAU,MAAM;AACd,QAAI,OAAO,iBAAiB,UAAU;AACpC,iBAAW;AAAgB,WACtB;AAAA,SACF,OAAO;AAAA;AAAA;AAAA,KAIX;AAEH,QAAM,eAAe,CAAC,MAAuC;AAC3D,UAAM;AAAA,MACJ,QAAQ,CAAE;AAAA,QACR;AAEJ,eAAW,iBAAe;AACxB,YAAM,EAAG,OAAO,WAAW,UAAW;AACtC,aAAO,QAAQ,IAAK,SAAS,OAAO,SAAoB;AAAA;AAAA;AAI5D,6CACG,aAAD;AAAA,IACE;AAAA,IACA,SAAQ;AAAA,IACR,WAAS;AAAA,IACT,eAAY;AAAA,yCAEX,YAAD;AAAA,IAAY,WAAW,QAAQ;AAAA,IAAO,QAAO;AAAA,KAC1C,2CAEF,QAAD;AAAA,IACE,SAAQ;AAAA,IACR,OAAO,QAAQ,SAAS;AAAA,IACxB,UAAU;AAAA,yCAET,UAAD;AAAA,IAAU,OAAM;AAAA,yCACb,MAAD,MAAI,SAEL,OAAO,IAAI,CAAC,8CACV,UAAD;AAAA,IAAU,KAAK;AAAA,IAAO;AAAA,KACnB;AAAA;MAQP,eAAe,CAAC,CAAE,WAAW,YAAY,+CAC5C,SAAD;AAAA,KAAa;AAAA;AAGf,aAAa,WAAW,CAAC,8CACtB,cAAD;AAAA,KAAkB;AAAA,EAAO,WAAW;AAAA;AAGtC,aAAa,SAAS,CAAC,8CACpB,cAAD;AAAA,KAAkB;AAAA,EAAO,WAAW;AAAA;MAShC,mBAAmB;;AChKzB,MAAMA,cAAYI,aAAW;AAAO,EAClC,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,YAAY;AAAA;AAAA,EAEd,OAAO;AAAA,IACL,MAAM;AAAA;AAAA;MAUG,YAAY,CAAC;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,MACoB;AACpB,QAAM,UAAUJ;AAEhB,6CACG,OAAD;AAAA,IACE,WAAU;AAAA,IACV,UAAU,OAAK,aAAa;AAAA,IAC5B,WAAW,QAAQ;AAAA,yCAElBK,cAAD;AAAA,IAAY,UAAQ;AAAA,IAAC,MAAK;AAAA,IAAS,cAAW;AAAA,yCAC3C,YAAD,4CAEDC,aAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,aAAY;AAAA,IACZ,OAAO;AAAA,IACP,UAAU,OAAK,aAAa;AAAA,IAC5B,YAAY,CAAE,cAAc;AAAA,0CAE7BD,cAAD;AAAA,IAAY,cAAW;AAAA,IAAS,SAAS,MAAM;AAAA,yCAC5C,aAAD;AAAA;;AC5CR,MAAML,cAAY,WAAW;AAAU,EACrC,SAAS;AAAA,IACP,OAAO;AAAA,IACP,SAAS;AAAA;AAAA,EAEX,MAAM;AAAA,IACJ,QAAQ,MAAM,QAAQ,IAAI,GAAG,GAAG;AAAA;AAAA;MASvB,gBAAgB,CAAC;AAAA,EAC5B;AAAA,EACA;AAAA,MACwB;AACxB,QAAM,UAAUA;AAEhB,6CACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,yCACrB,YAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,cAAW;AAAA,IACX,SAAS;AAAA,yCAER,gBAAD,4CAED,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAK,aACb,0BAA0B,0BAA0B,GAAE;AAAA;;AClBxE,MAAMA,cAAY,WAAW;AAAU,EACrC,SAAS;AAAA,IACP,YAAY;AAAA,IACZ,WAAW;AAAA;AAAA,EAEb,UAAU;AAAA,IACR,SAAS,MAAM,QAAQ,GAAG,GAAG,GAAG;AAAA;AAAA,EAElC,UAAU;AAAA,IACR,OAAO;AAAA;AAAA;MAsBE,UAAU,CAAC;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,MACkB;AAClB,QAAM,UAAUA;AAEhB,6CACG,MAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,yCACtB,YAAD;AAAA,IACE,2CAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,OAAK;AAAA,IAChC,4CACG,QAAD;AAAA,MAAQ,OAAM;AAAA,MAAU,SAAS,MAAM;AAAA,OAAgB;AAAA,0CAK1D,SAAD,OACC,cAAc,KAAK,WAAW,KAAK,cAAc,UAAU,WAAW,yCACpE,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,oDAKnC,cAAc,KAAK,SAAS,yCAC1B,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,6CAC/B,QAAD;AAAA,IACE,IAAG;AAAA,IACH,UAAU,CAAC,MAA2B;AAhGlD;AAiGc,4BAAe,6BAAG,WAAH,mBAAW;AAAA;AAAA,IAE5B,SAAQ;AAAA,IACR,WAAW,QAAQ;AAAA,IACnB,OAAO,QAAQ;AAAA,KAEd,cAAc,KAAK,IAAI,gDACrB,UAAD;AAAA,IACE,UAAU,WAAW;AAAA,IACrB,OAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,KAEN,YAMV,cAAc,UAAU,SAAS,yCAC/B,aAAD,0CACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,kDAC/B,MAAD;AAAA,IAAM,gBAAc;AAAA,IAAC,OAAK;AAAA,KACvB,cAAc,UAAU,IAAI,gDAC1B,UAAD;AAAA,IACE,KAAK;AAAA,IACL,OAAK;AAAA,IACL,QAAM;AAAA,IACN,SAAS,MAAM,cAAc;AAAA,yCAE5B,UAAD;AAAA,IACE,MAAK;AAAA,IACL,eAAa;AAAA,IACb,WAAW,QAAQ;AAAA,IACnB,OAAM;AAAA,IACN,SAAS,QAAQ,QAAQ,SAAS;AAAA,IAClC,UAAU;AAAA,IACV,OAAO;AAAA,IACP,MAAM;AAAA,0CAEP,cAAD;AAAA,IAAc,IAAI;AAAA,IAAQ,SAAS;AAAA;AAAA;;AC9FnD,MAAMA,cAAY,WAAW;AAAU,EACrC,aAAa;AAAA,IACX,OAAO,MAAM,QAAQ,KAAK;AAAA,IAC1B,YAAY,MAAM,QAAQ,WAAW;AAAA,IACrC,cAAc;AAAA;AAAA,EAEhB,aAAa;AAAA,IACX,QAAQ,MAAM,QAAQ,GAAG,GAAG,GAAG;AAAA,IAC/B,SAAS;AAAA;AAAA,EAEX,SAAS;AAAA,IACP,OAAO;AAAA,IACP,QAAQ,MAAM,QAAQ,GAAG;AAAA,IACzB,SAAS,MAAM,QAAQ,GAAG;AAAA;AAAA;AAgB9B,MAAM,UAAyB;AAAA,EAC7B;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA,IACP,WAAW;AAAA,IACX,QAAQ,CAAC,+CACN,MAAD;AAAA,MAAM,IAAI,OAAO,OAAO;AAAA,OAAK,OAAO;AAAA;AAAA,EAGxC;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA;AAAA,EAET;AAAA,IACE,OAAO;AAAA,IACP,OAAO;AAAA;AAAA;AAIX,MAAM,cAAc,CAAC;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,MACsB;AACtB,QAAM,UAAUA;AAEhB,6CACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,yCACrB,eAAD;AAAA,IACE;AAAA,IACA;AAAA,0CAED,SAAD;AAAA,IAAS,WAAW,QAAQ;AAAA,IAAS,aAAY;AAAA,0CAChD,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,KACZ,kDACE,YAAD;AAAA,IAAY,SAAQ;AAAA,KACjB,GAAG,oBACH,kBAAkB,IAAI,iBAAiB,mDACvC,QAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,KAAa,KAAE,aAAY,MAAS,2CAG9D,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAM,GAAG;AAAA;MAO1BO,iBAAe,CAAC,CAAE,iBAAqC;AAClE,QAAM,aAAa,OAAO;AAE1B,QAAM,CAAC,aAAa,iBAAiB,SAAS;AAC9C,QAAM,CAAC,iBAAiB,sBAAsB,SAAuB;AAAA,IACnE,UAAU;AAAA,IACV,SAAS;AAAA;AAGX,QAAM,CAAC,iBAAiB,sBAAsB,SAAwB;AAEtE,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,SAAS,YAAY;AACvB,UAAM,WAAW,MAAM,WAAW;AAClC,WAAO,SAAS,MAAM,IAAI,CAAC,WAAgB;AAlJ/C;AAkJmD;AAAA,QAC7C,MAAM,OAAO,SAAS;AAAA,QACtB,aAAa,OAAO,SAAS;AAAA,QAC7B,OACE,qBAAc,SAAP,mBAAa,WAAU,WAAW,aAAO,SAAP,mBAAa,QAAQ;AAAA,QAChE,MAAM,OAAO;AAAA,QACb,WACE,qBAAc,SAAP,mBAAa,eAAc,WAC9B,aAAO,SAAP,mBAAa,YACb;AAAA,QACN,KAAK,YACH,cAAO,SAAS,cAAhB,mBAA2B,kBAAiB,4BAC1C,OAAO,KAAK,iBAAiB,OAAO,SAAS;AAAA;AAAA;AAAA,KAElD;AAEH,YAAU,MAAM;AACd,QAAI,SAAS;AACX,UAAI,cAAc;AAKlB,UAAI,gBAAgB,aAAa,IAAI;AACnC,sBAAc,QAAQ,OAAO,CAAC,WAC5B,gBAAgB,SAAS,SAAS,OAAO;AAAA;AAK7C,UAAI,gBAAgB,QAAQ,SAAS,GAAG;AACtC,sBAAc,YAAY,OACxB,CAAC,WACC,OAAO,aACP,gBAAgB,QAAQ,SAAS,OAAO;AAAA;AAK9C,UAAI,aAAa;AACf,sBAAc,YAAY,OACxB,CAAC,WAAgB;AA3L3B;AA4LY,+BAAO,SAAP,mBAAa,kBAAkB,SAAS,SAAS,+BAC1C,SAAP,mBACI,kBAAkB,SACnB,SAAS,YAAY,MAAM,KAAK,KAAK,wBACjC,gBAAP,mBACI,kBAAkB,SACnB,SAAS;AAAA;AAAA;AAIlB,yBAAmB;AAAA;AAAA,KAEpB,CAAC,iBAAiB,aAAa;AAClC,MAAI,SAAS;AACX,+CAAQ,UAAD;AAAA;AAET,MAAI,OAAO;AACT,+CACG,OAAD;AAAA,MAAO,UAAS;AAAA,OAAQ,qDAC4B,MAAM;AAAA;AAI9D,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,+CAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,MAAO,OAAM;AAAA;AAAA;AAG1C,QAAM,eAAe,MAAM;AACzB,uBAAmB;AAAA,MACjB,UAAU;AAAA,MACV,SAAS;AAAA;AAAA;AAIb,QAAM,iBAAiB,CAAC,WAAmB;AACzC,uBAAmB;AAAc,SAC5B;AAAA,MACH,UAAU;AAAA;AAAA;AAId,QAAM,gBAAgB,CAAC,WAAmB;AACxC,QAAI,gBAAgB,QAAQ,SAAS,SAAS;AAC5C,yBAAmB;AAAc,WAC5B;AAAA,QACH,SAAS,UAAU,QAAQ,OAAO,UAAQ,SAAS;AAAA;AAErD;AAAA;AAGF,uBAAmB;AAAc,SAC5B;AAAA,MACH,SAAS,CAAC,GAAG,UAAU,SAAS;AAAA;AAAA;AAIpC,QAAM,gBAAgB,QAAQ,OAC5B,CAAC,KAAK,SAAS;AACb,QAAI,KAAK,QAAQ,IAAI,KAAK,QAAQ,KAAK,QAAQ,GAAG;AAChD,UAAI,KAAK,KAAK,KAAK;AAAA;AAErB,QAAI,KAAK,aAAa,IAAI,UAAU,QAAQ,KAAK,aAAa,GAAG;AAC/D,UAAI,UAAU,KAAK,KAAK;AAAA;AAE1B,WAAO;AAAA,KAET;AAAA,IACE,MAAM;AAAA,IACN,WAAW;AAAA;AAIf,uGAEK,MAAD;AAAA,IAAM,WAAS;AAAA,KACZ,mDACE,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,yCACZ,SAAD;AAAA,IACE,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,2CAIL,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI,cAAc,IAAI;AAAA,yCAC9B,OAAD;AAAA,IACE,SAAS,CAAE,QAAQ,MAAM,UAAU,IAAI,QAAQ;AAAA,IAC/C,MAAM;AAAA,IACN;AAAA,IACA,2CACG,aAAD;AAAA,MACE;AAAA,MACA,iBAAiB,gBAAgB;AAAA,MACjC,yBACG,iBAAgB,aAAa,KAAK,IAAI,KACvC,gBAAgB,QAAQ;AAAA,MAE1B,qBAAqB,MAAM,cAAc,CAAC;AAAA;AAAA;AAAA;;MChQ7C,mBAAmB,MAAM;AACpC,QAAM,CAAC,aAAa,kBAAkB,mBAA2B;AACjE,QAAM,CAAC,aAAa,kBAAkB,SAAS,oCAAe;AAE9D,QAAM,eAAe,CAAC,UAA+C;AACnE,UAAM;AACN,mBAAe,MAAM,OAAO;AAAA;AAG9B,YAAU,MAAM,eAAe,oCAAe,KAAK,CAAC;AAEpD,cACE,MAAM;AACJ,mBAAe;AAAA,KAEjB,KACA,CAAC;AAGH,QAAM,uBAAuB,MAAM;AACjC,mBAAe;AAAA;AAGjB,6CACG,MAAD;AAAA,IAAM,SAAQ;AAAA,yCACX,QAAD;AAAA,IAAQ,OAAM;AAAA,0CACb,SAAD,0CACG,MAAD;AAAA,IAAM,WAAS;AAAA,IAAC,WAAU;AAAA,yCACvB,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,yCACZ,WAAD;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,2CAGH,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,yCACZA,gBAAD;AAAA,IACE,aAAc,qCAAe,IAAI,kBAAkB;AAAA;AAAA;;MC5CpD,aAAa,MAAM;AAC9B,QAAM,WAAW;AACjB,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,MACE;AAEJ,QAAM,kBAAkB,YAAY,SAAS;AAC7C,YAAU,MAAM;AAEd,QAAI,SAAS,WAAW,iBAAiB;AACvC;AAAA;AAGF,UAAM,QACJ,GAAG,MAAM,SAAS,OAAO,UAAU,IAAI,CAAE,YAAY,OAAQ;AAE/D,QAAI,MAAM,SAAS;AACjB,iBAAW,MAAM;AAAA;AAGnB,QAAI,MAAM,OAAO;AACf,cAAQ,MAAM;AAAA;AAGhB,QAAI,MAAM,YAAY;AACpB,oBAAc,MAAM;AAAA;AAGtB,QAAI,MAAM,OAAO;AACf,eAAS,MAAM;AAAA;AAAA,KAEhB,CAAC,iBAAiB,UAAU,SAAS,UAAU,eAAe;AAEjE,YAAU,MAAM;AACd,UAAM,YAAY,GAAG,UACnB;AAAA,MACE,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,OAEF,CAAE,aAAa;AAEjB,UAAM,SAAS,GAAG,OAAO,SAAS,YAAY;AAM9C,WAAO,QAAQ,aAAa,MAAM,SAAS,OAAO;AAAA,KACjD,CAAC,MAAM,OAAO,YAAY;AAE7B,SAAO;AAAA;MAGIC,eAAa,MAAM;AAC9B,QAAM,SAAS;AAEf,6CACG,uBAAD,0CACG,YAAD,OACC,8CAAW,kBAAD;AAAA;;ACtEjB,MAAMR,cAAY,WAAW;AAAU,EACrC,MAAM;AAAA,IACJ,SAAS;AAAA,IACT,gBAAgB;AAAA,IAChB,KAAK,MAAM,QAAQ;AAAA,IACnB,QAAQ,MAAM,QAAQ;AAAA;AAAA;MAIb,oBAAoB,MAAM;AACrC,QAAM,CAAE,eAAe,qBAAsB;AAC7C,QAAM,UAAUA;AAEhB,MAAI,CAAC,iBAAiB,CAAC,mBAAmB;AACxC;AAAO;AAGT,6CACG,OAAD;AAAA,IAAK,eAAY;AAAA,IAAwB,WAAW,QAAQ;AAAA,yCACzD,QAAD;AAAA,IACE,cAAW;AAAA,IACX,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,IACT,+CAAY,kBAAD;AAAA,IACX,MAAK;AAAA,KACN,6CAIA,QAAD;AAAA,IACE,cAAW;AAAA,IACX,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,IACT,6CAAU,qBAAD;AAAA,IACT,MAAK;AAAA,KACN;AAAA;;AC5BP,MAAM,YAAY,WAAW;AAAU,EACrC,OAAO;AAAA,IACL,eAAe;AAAA;AAAA,EAEjB,OAAO;AAAA,IACL,SAAS;AAAA,IACT,UAAU;AAAA,IACV,WAAW,MAAM,QAAQ;AAAA;AAAA,EAE3B,MAAM;AAAA,IACJ,QAAQ;AAAA;AAAA;MAWN,aAAa,CAAC;AAAA,EAClB,SAAS;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,MACqB;AACrB,QAAM,UAAU;AAChB,QAAM,CAAE,OAAO,YAAa;AAE5B,gBAAc,MAAM;AAClB,QAAI,CAAC,MAAM,QAAQ;AACjB,UAAI,gBAAgB,MAAM,QAAQ,eAAe;AAC/C,iBAAS;AAAA,iBACA,cAAc;AACvB,iBAAS,CAAC;AAAA;AAAA;AAAA;AAKhB,QAAM,eAAe,CAAC,MAAuC;AAC3D,UAAM,QAAQ,EAAE,OAAO;AACvB,aAAS;AAAA;AAGX,6CACG,aAAD;AAAA,IACE;AAAA,IACA,SAAQ;AAAA,IACR,WAAS;AAAA,IACT,eAAY;AAAA,yCAEX,YAAD;AAAA,IAAY,WAAW,QAAQ;AAAA,IAAO,QAAO;AAAA,KAC1C,2CAEF,QAAD;AAAA,IACE,UAAQ;AAAA,IACR,SAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,IACV,aAAY;AAAA,IACZ,aAAa,kDACV,OAAD;AAAA,MAAK,WAAW,QAAQ;AAAA,OACpB,SAAsB,IAAI,+CACzB,MAAD;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,MAAK;AAAA;AAAA,KAMZ,OAAO,IAAI,CAAC,8CACV,UAAD;AAAA,IAAU,KAAK;AAAA,IAAO;AAAA,yCACnB,UAAD;AAAA,IAAU,SAAS,MAAM,QAAQ,SAAS;AAAA,0CACzC,cAAD;AAAA,IAAc,SAAS;AAAA;AAAA;;MC/EtB,eAAe,eAAe;AAAA,EACzC,MAAM;AAAA,EACN,OAAO;AAAA;MAGI,mBAAmB,eAAe;AAAA,EAC7C,MAAM;AAAA,EACN,OAAO;AAAA;MAGI,eAAe,aAAa;AAAA,EACvC,IAAI;AAAA,EACJ,MAAM;AAAA,IACJ,iBAAiB;AAAA,MACf,KAAK;AAAA,MACL,MAAM,CAAE,cAAc,iBAAiB,aAAa;AAAA,MACpD,SAAS,CAAC,CAAE,cAAc,iBAAkB;AAC1C,eAAO,IAAI,aAAa,CAAE,cAAc;AAAA;AAAA;AAAA;AAAA,EAI9C,QAAQ;AAAA,IACN,MAAM;AAAA,IACN,UAAU;AAAA;AAAA;MAID,aAAa,aAAa,QACrC,wBAAwB;AAAA,EACtB,WAAW,MAAa,kCAA2B,KAAK,OAAK,EAAE;AAAA,EAC/D,YAAY;AAAA;MAUH,iBAAiB,aAAa,QACzC,wBAAwB;AAAA,EACtB,WAAW,MAAa,kCAA2B,KAAK,OAAK,EAAE;AAAA,EAC/D,YAAY;AAAA;AAIS,aAAa,QACpC,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MAAa,kCAA0B,KAAK,OAAK,EAAE;AAAA;AAAA;MAWlD,gBAAgB,aAAa,QACxC,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MAAa,kCAA0B,KAAK,OAAK,EAAE;AAAA;AAAA;MAKlD,eAAe,aAAa,QACvC,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MAAa,kCAA6B,KAAK,OAAK,EAAE;AAAA;AAAA;AAWlC,aAAa,QAC3C,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MAAa,kCAA6B,KAAK,OAAK,EAAE;AAAA;AAAA;MAKrD,wBAAwB,aAAa,QAChD,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MACG,kCAAsC,KAC3C,OAAK,EAAE;AAAA;AAAA;MAMJ,oBAAoB,aAAa,QAC5C,yBAAyB;AAAA,EACvB,WAAW;AAAA,IACT,MAAM,MACG,kCAAkC,KAAK,OAAK,EAAE;AAAA;AAAA;;MC9GhD,gBAAgB,MAAM;AACjC,QAAM,cAAc,YAAY;AAChC,QAAM,WAAW;AACjB,QAAM,eAAe,YACnB,CAAC,UAAwB;AACvB,UAAM,cAAc,GAAG,UAAU,CAAE,QAAS,CAAE,gBAAgB;AAE9D,aAAS,GAAG,gBAAgB;AAAA,KAE9B,CAAC,UAAU;AAGb,6CAAQ,oBAAD;AAAA,IAAoB,UAAU;AAAA,IAAc,IAAG;AAAA;AAAA;;;;"}
|