@backstage/plugin-search 0.4.17 → 0.4.18
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 +12 -0
- package/dist/esm/{index-226c47ca.esm.js → index-01b40466.esm.js} +2 -2
- package/dist/esm/{index-226c47ca.esm.js.map → index-01b40466.esm.js.map} +1 -1
- package/dist/esm/{index-12477c15.esm.js → index-207637ef.esm.js} +2 -2
- package/dist/esm/index-207637ef.esm.js.map +1 -0
- package/dist/esm/{index-022e0330.esm.js → index-766e727c.esm.js} +2 -2
- package/dist/esm/index-766e727c.esm.js.map +1 -0
- package/dist/esm/{index-3b720a86.esm.js → index-77205085.esm.js} +2 -2
- package/dist/esm/index-77205085.esm.js.map +1 -0
- package/dist/esm/{index-597d3990.esm.js → index-b929d40d.esm.js} +2 -2
- package/dist/esm/index-b929d40d.esm.js.map +1 -0
- package/dist/esm/{index-b3bf028c.esm.js → index-b9474e70.esm.js} +2 -2
- package/dist/esm/{index-b3bf028c.esm.js.map → index-b9474e70.esm.js.map} +1 -1
- package/dist/esm/{index-17c9e868.esm.js → index-cdccd881.esm.js} +22 -21
- package/dist/esm/index-cdccd881.esm.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.esm.js +1 -1
- package/package.json +10 -10
- package/dist/esm/index-022e0330.esm.js.map +0 -1
- package/dist/esm/index-12477c15.esm.js.map +0 -1
- package/dist/esm/index-17c9e868.esm.js.map +0 -1
- package/dist/esm/index-3b720a86.esm.js.map +0 -1
- package/dist/esm/index-597d3990.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @backstage/plugin-search
|
|
2
2
|
|
|
3
|
+
## 0.4.18
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- a125278b81: Refactor out the deprecated path and icon from RouteRefs
|
|
8
|
+
- 704b267e1c: Smaller UX improvements to search components such as optional autoFocus prop to SearchBar components, decreased debounce value and closing modal on link click of SearchModal, terminology updates of SearchResultPager.
|
|
9
|
+
- Updated dependencies
|
|
10
|
+
- @backstage/catalog-model@0.9.7
|
|
11
|
+
- @backstage/plugin-catalog-react@0.6.4
|
|
12
|
+
- @backstage/core-components@0.7.4
|
|
13
|
+
- @backstage/core-plugin-api@0.2.0
|
|
14
|
+
|
|
3
15
|
## 0.4.17
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React__default, { useState } from 'react';
|
|
2
2
|
import SearchIcon from '@material-ui/icons/Search';
|
|
3
|
-
import { d as SearchModal } from './index-
|
|
3
|
+
import { d as SearchModal } from './index-cdccd881.esm.js';
|
|
4
4
|
import { SidebarItem } from '@backstage/core-components';
|
|
5
5
|
import '@backstage/core-plugin-api';
|
|
6
6
|
import '@backstage/errors';
|
|
@@ -36,4 +36,4 @@ const SidebarSearchModal = () => {
|
|
|
36
36
|
};
|
|
37
37
|
|
|
38
38
|
export { SidebarSearchModal };
|
|
39
|
-
//# sourceMappingURL=index-
|
|
39
|
+
//# sourceMappingURL=index-01b40466.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-01b40466.esm.js","sources":["../../src/components/SidebarSearchModal/SidebarSearchModal.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 React, { useState } from 'react';\nimport SearchIcon from '@material-ui/icons/Search';\nimport { SearchModal } from '../SearchModal';\nimport { SidebarItem } from '@backstage/core-components';\n\nexport const SidebarSearchModal = () => {\n const [open, setOpen] = useState<boolean>(false);\n const toggleModal = (): void => setOpen(prevState => !prevState);\n\n return (\n <>\n <SidebarItem\n className=\"search-icon\"\n icon={SearchIcon}\n text=\"Search\"\n onClick={toggleModal}\n />\n <SearchModal open={open} toggleModal={toggleModal} />\n </>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;MAoBa,qBAAqB,MAAM;AACtC,QAAM,CAAC,MAAM,WAAW,SAAkB;AAC1C,QAAM,cAAc,MAAY,QAAQ,eAAa,CAAC;AAEtD,kIAEK,aAAD;AAAA,IACE,WAAU;AAAA,IACV,MAAM;AAAA,IACN,MAAK;AAAA,IACL,SAAS;AAAA,mDAEV,aAAD;AAAA,IAAa;AAAA,IAAY;AAAA;AAAA;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { D as DefaultResultListItem } from './index-
|
|
1
|
+
export { D as DefaultResultListItem } from './index-cdccd881.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -20,4 +20,4 @@ import '@material-ui/lab';
|
|
|
20
20
|
import '@backstage/plugin-catalog-react';
|
|
21
21
|
import '@backstage/catalog-model';
|
|
22
22
|
import 'react-router-dom';
|
|
23
|
-
//# sourceMappingURL=index-
|
|
23
|
+
//# sourceMappingURL=index-207637ef.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-207637ef.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { c as SearchResult } from './index-
|
|
1
|
+
export { c as SearchResult } from './index-cdccd881.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -20,4 +20,4 @@ import '@material-ui/lab';
|
|
|
20
20
|
import '@backstage/plugin-catalog-react';
|
|
21
21
|
import '@backstage/catalog-model';
|
|
22
22
|
import 'react-router-dom';
|
|
23
|
-
//# sourceMappingURL=index-
|
|
23
|
+
//# sourceMappingURL=index-766e727c.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-766e727c.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { S as SearchPage } from './index-
|
|
1
|
+
export { S as SearchPage } from './index-cdccd881.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -20,4 +20,4 @@ import '@material-ui/lab';
|
|
|
20
20
|
import '@backstage/plugin-catalog-react';
|
|
21
21
|
import '@backstage/catalog-model';
|
|
22
22
|
import 'react-router-dom';
|
|
23
|
-
//# sourceMappingURL=index-
|
|
23
|
+
//# sourceMappingURL=index-77205085.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-77205085.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-cdccd881.esm.js';
|
|
2
2
|
import '@backstage/core-plugin-api';
|
|
3
3
|
import '@backstage/errors';
|
|
4
4
|
import 'qs';
|
|
@@ -20,4 +20,4 @@ import '@material-ui/lab';
|
|
|
20
20
|
import '@backstage/plugin-catalog-react';
|
|
21
21
|
import '@backstage/catalog-model';
|
|
22
22
|
import 'react-router-dom';
|
|
23
|
-
//# sourceMappingURL=index-
|
|
23
|
+
//# sourceMappingURL=index-b929d40d.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-b929d40d.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React__default, { 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-cdccd881.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';
|
|
@@ -57,4 +57,4 @@ const HomePageSearchBar = ({placeholder}) => {
|
|
|
57
57
|
};
|
|
58
58
|
|
|
59
59
|
export { HomePageSearchBar };
|
|
60
|
-
//# sourceMappingURL=index-
|
|
60
|
+
//# sourceMappingURL=index-b9474e70.esm.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index-
|
|
1
|
+
{"version":3,"file":"index-b9474e70.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":["React"],"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,YAAYA,eAAM,SAAS;AACzC,QAAM,eAAe;AACrB,QAAM,UAAU;AAEhB,QAAM,eAAe,MAAM;AACzB,iBAAa,CAAE;AAAA;AAGjB,QAAM,eAAeA,eAAM,YACzB,WAAS;AACP,aAAS;AAAA,KAEX,CAAC;AAGH,sDACG,eAAD;AAAA,IACE,UAAU;AAAA,IACV,UAAU;AAAA,IACV,OAAO;AAAA,IACP,WAAW,QAAQ;AAAA,IACnB;AAAA;AAAA;;;;"}
|
|
@@ -219,6 +219,7 @@ const useSearch = () => {
|
|
|
219
219
|
};
|
|
220
220
|
|
|
221
221
|
const SearchBarBase = ({
|
|
222
|
+
autoFocus,
|
|
222
223
|
value,
|
|
223
224
|
onChange,
|
|
224
225
|
onSubmit,
|
|
@@ -236,6 +237,7 @@ const SearchBarBase = ({
|
|
|
236
237
|
}, [onChange]);
|
|
237
238
|
const placeholder = overridePlaceholder != null ? overridePlaceholder : `Search in ${configApi.getOptionalString("app.title") || "Backstage"}`;
|
|
238
239
|
return /* @__PURE__ */ React__default.createElement(InputBase, {
|
|
240
|
+
autoFocus,
|
|
239
241
|
"data-testid": "search-bar-next",
|
|
240
242
|
fullWidth: true,
|
|
241
243
|
placeholder,
|
|
@@ -259,6 +261,7 @@ const SearchBarBase = ({
|
|
|
259
261
|
});
|
|
260
262
|
};
|
|
261
263
|
const SearchBar$1 = ({
|
|
264
|
+
autoFocus,
|
|
262
265
|
className,
|
|
263
266
|
debounceTime = 0,
|
|
264
267
|
placeholder
|
|
@@ -274,6 +277,7 @@ const SearchBar$1 = ({
|
|
|
274
277
|
};
|
|
275
278
|
const handleClear = () => setValue("");
|
|
276
279
|
return /* @__PURE__ */ React__default.createElement(SearchBarBase, {
|
|
280
|
+
autoFocus,
|
|
277
281
|
className,
|
|
278
282
|
value,
|
|
279
283
|
onChange: handleQuery,
|
|
@@ -425,7 +429,7 @@ const useStyles$6 = makeStyles((theme) => ({
|
|
|
425
429
|
display: "flex",
|
|
426
430
|
justifyContent: "space-between",
|
|
427
431
|
gap: theme.spacing(2),
|
|
428
|
-
margin: theme.spacing(
|
|
432
|
+
margin: theme.spacing(2, 0)
|
|
429
433
|
}
|
|
430
434
|
}));
|
|
431
435
|
const SearchResultPager = () => {
|
|
@@ -441,24 +445,20 @@ const SearchResultPager = () => {
|
|
|
441
445
|
"aria-label": "previous page",
|
|
442
446
|
disabled: !fetchPreviousPage,
|
|
443
447
|
onClick: fetchPreviousPage,
|
|
444
|
-
startIcon: /* @__PURE__ */ React__default.createElement(ArrowBackIosIcon, null)
|
|
445
|
-
|
|
446
|
-
}, "Back"), /* @__PURE__ */ React__default.createElement(Button, {
|
|
448
|
+
startIcon: /* @__PURE__ */ React__default.createElement(ArrowBackIosIcon, null)
|
|
449
|
+
}, "Previous"), /* @__PURE__ */ React__default.createElement(Button, {
|
|
447
450
|
"aria-label": "next page",
|
|
448
451
|
disabled: !fetchNextPage,
|
|
449
452
|
onClick: fetchNextPage,
|
|
450
|
-
endIcon: /* @__PURE__ */ React__default.createElement(ArrowForwardIosIcon, null)
|
|
451
|
-
size: "small"
|
|
453
|
+
endIcon: /* @__PURE__ */ React__default.createElement(ArrowForwardIosIcon, null)
|
|
452
454
|
}, "Next"));
|
|
453
455
|
};
|
|
454
456
|
|
|
455
457
|
const rootRouteRef = createRouteRef({
|
|
456
|
-
|
|
457
|
-
title: "search"
|
|
458
|
+
id: "search"
|
|
458
459
|
});
|
|
459
460
|
const rootNextRouteRef = createRouteRef({
|
|
460
|
-
|
|
461
|
-
title: "search"
|
|
461
|
+
id: "search:next"
|
|
462
462
|
});
|
|
463
463
|
const searchPlugin = createPlugin({
|
|
464
464
|
id: "search",
|
|
@@ -478,54 +478,54 @@ const searchPlugin = createPlugin({
|
|
|
478
478
|
});
|
|
479
479
|
const SearchPage$1 = searchPlugin.provide(createRoutableExtension({
|
|
480
480
|
name: "SearchPage",
|
|
481
|
-
component: () => import('./index-
|
|
481
|
+
component: () => import('./index-77205085.esm.js').then((m) => m.SearchPage),
|
|
482
482
|
mountPoint: rootRouteRef
|
|
483
483
|
}));
|
|
484
484
|
const SearchPageNext = searchPlugin.provide(createRoutableExtension({
|
|
485
485
|
name: "SearchPageNext",
|
|
486
|
-
component: () => import('./index-
|
|
486
|
+
component: () => import('./index-77205085.esm.js').then((m) => m.SearchPage),
|
|
487
487
|
mountPoint: rootNextRouteRef
|
|
488
488
|
}));
|
|
489
489
|
searchPlugin.provide(createComponentExtension({
|
|
490
490
|
name: "SearchBar",
|
|
491
491
|
component: {
|
|
492
|
-
lazy: () => import('./index-
|
|
492
|
+
lazy: () => import('./index-b929d40d.esm.js').then((m) => m.SearchBar)
|
|
493
493
|
}
|
|
494
494
|
}));
|
|
495
495
|
const SearchBarNext = searchPlugin.provide(createComponentExtension({
|
|
496
496
|
name: "SearchBarNext",
|
|
497
497
|
component: {
|
|
498
|
-
lazy: () => import('./index-
|
|
498
|
+
lazy: () => import('./index-b929d40d.esm.js').then((m) => m.SearchBar)
|
|
499
499
|
}
|
|
500
500
|
}));
|
|
501
501
|
const SearchResult$1 = searchPlugin.provide(createComponentExtension({
|
|
502
502
|
name: "SearchResult",
|
|
503
503
|
component: {
|
|
504
|
-
lazy: () => import('./index-
|
|
504
|
+
lazy: () => import('./index-766e727c.esm.js').then((m) => m.SearchResult)
|
|
505
505
|
}
|
|
506
506
|
}));
|
|
507
507
|
searchPlugin.provide(createComponentExtension({
|
|
508
508
|
name: "SearchResultNext",
|
|
509
509
|
component: {
|
|
510
|
-
lazy: () => import('./index-
|
|
510
|
+
lazy: () => import('./index-766e727c.esm.js').then((m) => m.SearchResult)
|
|
511
511
|
}
|
|
512
512
|
}));
|
|
513
513
|
const SidebarSearchModal = searchPlugin.provide(createComponentExtension({
|
|
514
514
|
name: "SidebarSearchModal",
|
|
515
515
|
component: {
|
|
516
|
-
lazy: () => import('./index-
|
|
516
|
+
lazy: () => import('./index-01b40466.esm.js').then((m) => m.SidebarSearchModal)
|
|
517
517
|
}
|
|
518
518
|
}));
|
|
519
519
|
const DefaultResultListItem = searchPlugin.provide(createComponentExtension({
|
|
520
520
|
name: "DefaultResultListItem",
|
|
521
521
|
component: {
|
|
522
|
-
lazy: () => import('./index-
|
|
522
|
+
lazy: () => import('./index-207637ef.esm.js').then((m) => m.DefaultResultListItem)
|
|
523
523
|
}
|
|
524
524
|
}));
|
|
525
525
|
const HomePageSearchBar = searchPlugin.provide(createComponentExtension({
|
|
526
526
|
name: "HomePageSearchBar",
|
|
527
527
|
component: {
|
|
528
|
-
lazy: () => import('./index-
|
|
528
|
+
lazy: () => import('./index-b9474e70.esm.js').then((m) => m.HomePageSearchBar)
|
|
529
529
|
}
|
|
530
530
|
}));
|
|
531
531
|
|
|
@@ -550,7 +550,7 @@ const Modal = ({open = true, toggleModal}) => {
|
|
|
550
550
|
useEffect(() => {
|
|
551
551
|
setValue((prevValue) => prevValue !== term ? term : prevValue);
|
|
552
552
|
}, [term]);
|
|
553
|
-
useDebounce(() => setTerm(value),
|
|
553
|
+
useDebounce(() => setTerm(value), 500, [value]);
|
|
554
554
|
const handleQuery = (newValue) => {
|
|
555
555
|
setValue(newValue);
|
|
556
556
|
};
|
|
@@ -586,6 +586,7 @@ const Modal = ({open = true, toggleModal}) => {
|
|
|
586
586
|
}, /* @__PURE__ */ React__default.createElement(Grid, {
|
|
587
587
|
item: true
|
|
588
588
|
}, /* @__PURE__ */ React__default.createElement(Link, {
|
|
589
|
+
onClick: toggleModal,
|
|
589
590
|
to: `${getSearchLink()}?query=${value}`
|
|
590
591
|
}, /* @__PURE__ */ React__default.createElement("span", {
|
|
591
592
|
className: classes.viewResultsLink
|
|
@@ -1104,4 +1105,4 @@ const SidebarSearch = () => {
|
|
|
1104
1105
|
};
|
|
1105
1106
|
|
|
1106
1107
|
export { DefaultResultListItem$1 as D, Filters$1 as F, HomePageSearchBar as H, SearchPage as S, SearchBar$1 as a, SearchBarBase as b, SearchResultComponent as c, SearchModal as d, FiltersButton$1 as e, SearchContextProvider as f, SearchFilter as g, SearchFilterNext as h, SearchResultPager as i, SearchType as j, SidebarSearch as k, DefaultResultListItem as l, SearchBarNext as m, SearchPage$1 as n, SearchPageNext as o, searchPlugin as p, SearchResult$1 as q, rootRouteRef as r, searchApiRef as s, SidebarSearchModal as t, useSearch as u };
|
|
1107
|
-
//# sourceMappingURL=index-
|
|
1108
|
+
//# sourceMappingURL=index-cdccd881.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-cdccd881.esm.js","sources":["../../src/apis.ts","../../src/components/DefaultResultListItem/DefaultResultListItem.tsx","../../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","../../../../node_modules/@material-ui/icons/esm/Launch.js","../../src/components/SearchResult/SearchResult.tsx","../../src/components/SearchResultPager/SearchResultPager.tsx","../../src/plugin.ts","../../src/components/SearchModal/SearchModal.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/SearchType/SearchType.tsx","../../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 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 { IndexableDocument } from '@backstage/search-common';\nimport { ListItem, ListItemText, Divider } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\n\ntype Props = {\n result: IndexableDocument;\n};\n\nexport const DefaultResultListItem = ({ result }: Props) => {\n return (\n <Link to={result.location}>\n <ListItem alignItems=\"flex-start\">\n <ListItemText\n primaryTypographyProps={{ variant: 'h6' }}\n primary={result.title}\n secondary={result.text}\n />\n </ListItem>\n <Divider />\n </Link>\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 autoFocus?: boolean;\n};\n\nexport const SearchBarBase = ({\n autoFocus,\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 // decision up to adopter, read https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md#no-autofocus\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={autoFocus}\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 autoFocus?: boolean;\n className?: string;\n debounceTime?: number;\n placeholder?: string;\n};\n\nexport const SearchBar = ({\n autoFocus,\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 // decision up to adopter, read https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/master/docs/rules/no-autofocus.md#no-autofocus\n // eslint-disable-next-line jsx-a11y/no-autofocus\n autoFocus={autoFocus}\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","import * as React from 'react';\nimport createSvgIcon from './utils/createSvgIcon';\nexport default createSvgIcon( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z\"\n}), 'Launch');","/*\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","/*\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(2, 0),\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 >\n Previous\n </Button>\n\n <Button\n aria-label=\"next page\"\n disabled={!fetchNextPage}\n onClick={fetchNextPage}\n endIcon={<ArrowForwardIosIcon />}\n >\n Next\n </Button>\n </nav>\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 { 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 id: 'search',\n});\n\nexport const rootNextRouteRef = createRouteRef({\n id: 'search:next',\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 SidebarSearchModal = searchPlugin.provide(\n createComponentExtension({\n name: 'SidebarSearchModal',\n component: {\n lazy: () =>\n import('./components/SidebarSearchModal').then(\n m => m.SidebarSearchModal,\n ),\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 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 React, { useEffect, useState } from 'react';\nimport {\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Divider,\n Grid,\n List,\n Paper,\n} from '@material-ui/core';\nimport { Launch } from '@material-ui/icons/';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { SearchBarBase } from '../SearchBar';\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResult } from '../SearchResult';\nimport { SearchContextProvider, useSearch } from '../SearchContext';\nimport { SearchResultPager } from '../SearchResultPager';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { Link } from '@backstage/core-components';\nimport { rootRouteRef } from '../../plugin';\n\nimport { useDebounce } from 'react-use';\n\nexport interface SearchModalProps {\n open?: boolean;\n toggleModal: () => void;\n}\n\nconst useStyles = makeStyles(theme => ({\n container: {\n borderRadius: 30,\n display: 'flex',\n height: '2.4em',\n },\n input: {\n flex: 1,\n },\n // Reduces default height of the modal, keeping a gap of 128px between the top and bottom of the page.\n paperFullWidth: { height: 'calc(100% - 128px)' },\n dialogActionsContainer: { padding: theme.spacing(1, 3) },\n viewResultsLink: { verticalAlign: '0.5em' },\n}));\n\nexport const Modal = ({ open = true, toggleModal }: SearchModalProps) => {\n const getSearchLink = useRouteRef(rootRouteRef);\n const classes = useStyles();\n\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), 500, [value]);\n\n const handleQuery = (newValue: string) => {\n setValue(newValue);\n };\n\n const handleClear = () => setValue('');\n\n const handleResultClick = () => {\n toggleModal();\n handleClear();\n };\n\n const handleKeyPress = () => {\n handleResultClick();\n };\n\n return (\n <Dialog\n classes={{\n paperFullWidth: classes.paperFullWidth,\n }}\n onClose={toggleModal}\n aria-labelledby=\"search-modal-title\"\n open={open}\n fullWidth\n maxWidth=\"lg\"\n >\n <DialogTitle>\n <Paper className={classes.container}>\n <SearchBarBase\n className={classes.input}\n value={value}\n onChange={handleQuery}\n onClear={handleClear}\n />\n </Paper>\n </DialogTitle>\n <DialogContent>\n <Grid\n container\n direction=\"row-reverse\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid item>\n <Link\n onClick={toggleModal}\n to={`${getSearchLink()}?query=${value}`}\n >\n <span className={classes.viewResultsLink}>View Full Results</span>\n <Launch color=\"primary\" />\n </Link>\n </Grid>\n </Grid>\n <Divider />\n <SearchResult>\n {({ results }) => (\n <List>\n {results.map(({ document }) => (\n <div\n role=\"button\"\n tabIndex={0}\n key={`${document.location}-btn`}\n onClick={handleResultClick}\n onKeyPress={handleKeyPress}\n >\n <DefaultResultListItem\n key={document.location}\n result={document}\n />\n </div>\n ))}\n </List>\n )}\n </SearchResult>\n </DialogContent>\n <DialogActions className={classes.dialogActionsContainer}>\n <Grid container direction=\"row\">\n <Grid item xs={12}>\n <SearchResultPager />\n </Grid>\n </Grid>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const SearchModal = ({ open = true, toggleModal }: SearchModalProps) => {\n return (\n <SearchContextProvider>\n <Modal open={open} toggleModal={toggleModal} />\n </SearchContextProvider>\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 { 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 */\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 */\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":["DefaultResultListItem","useStyles","FiltersButton","Filters","React","SearchBar","SearchPage","SearchResult","makeStyles","IconButton","InputBase"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -35,11 +35,12 @@ declare type FiltersProps = {
|
|
|
35
35
|
declare const Filters: ({ filters, filterOptions, resetFilters, updateSelected, updateChecked, }: FiltersProps) => JSX.Element;
|
|
36
36
|
|
|
37
37
|
declare type Props$1 = {
|
|
38
|
+
autoFocus?: boolean;
|
|
38
39
|
className?: string;
|
|
39
40
|
debounceTime?: number;
|
|
40
41
|
placeholder?: string;
|
|
41
42
|
};
|
|
42
|
-
declare const SearchBar: ({ className, debounceTime, placeholder, }: Props$1) => JSX.Element;
|
|
43
|
+
declare const SearchBar: ({ autoFocus, className, debounceTime, placeholder, }: Props$1) => JSX.Element;
|
|
43
44
|
|
|
44
45
|
declare type SearchContextValue = {
|
|
45
46
|
result: AsyncState<SearchResultSet>;
|
|
@@ -125,7 +126,8 @@ declare const SearchPageNext: () => JSX.Element;
|
|
|
125
126
|
* <SearchBar /> component instead. This component will be removed in an
|
|
126
127
|
* upcoming release.
|
|
127
128
|
*/
|
|
128
|
-
declare const SearchBarNext: ({ className, debounceTime, placeholder, }: {
|
|
129
|
+
declare const SearchBarNext: ({ autoFocus, className, debounceTime, placeholder, }: {
|
|
130
|
+
autoFocus?: boolean | undefined;
|
|
129
131
|
className?: string | undefined;
|
|
130
132
|
debounceTime?: number | undefined;
|
|
131
133
|
placeholder?: string | undefined;
|
package/dist/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { l as DefaultResultListItem, F as Filters, e as FiltersButton, H as HomePageSearchBar, S as Router, a as SearchBar, m as SearchBarNext, f as SearchContextProvider, g as SearchFilter, h as SearchFilterNext, d as SearchModal, n as SearchPage, o as SearchPageNext, q as SearchResult, i as SearchResultPager, j as SearchType, k as SidebarSearch, t as SidebarSearchModal, p as plugin, s as searchApiRef, p as searchPlugin, u as useSearch } from './esm/index-
|
|
1
|
+
export { l as DefaultResultListItem, F as Filters, e as FiltersButton, H as HomePageSearchBar, S as Router, a as SearchBar, m as SearchBarNext, f as SearchContextProvider, g as SearchFilter, h as SearchFilterNext, d as SearchModal, n as SearchPage, o as SearchPageNext, q as SearchResult, i as SearchResultPager, j as SearchType, k as SidebarSearch, t as SidebarSearchModal, p as plugin, s as searchApiRef, p as searchPlugin, u as useSearch } from './esm/index-cdccd881.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.18",
|
|
5
5
|
"main": "dist/index.esm.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
@@ -30,12 +30,12 @@
|
|
|
30
30
|
"clean": "backstage-cli clean"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@backstage/catalog-model": "^0.9.
|
|
33
|
+
"@backstage/catalog-model": "^0.9.7",
|
|
34
34
|
"@backstage/config": "^0.1.11",
|
|
35
|
-
"@backstage/core-components": "^0.7.
|
|
36
|
-
"@backstage/core-plugin-api": "^0.
|
|
35
|
+
"@backstage/core-components": "^0.7.4",
|
|
36
|
+
"@backstage/core-plugin-api": "^0.2.0",
|
|
37
37
|
"@backstage/errors": "^0.1.4",
|
|
38
|
-
"@backstage/plugin-catalog-react": "^0.6.
|
|
38
|
+
"@backstage/plugin-catalog-react": "^0.6.4",
|
|
39
39
|
"@backstage/search-common": "^0.2.1",
|
|
40
40
|
"@backstage/theme": "^0.2.13",
|
|
41
41
|
"@backstage/types": "^0.1.1",
|
|
@@ -51,10 +51,10 @@
|
|
|
51
51
|
"react-use": "^17.2.4"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
|
-
"@backstage/cli": "^0.
|
|
55
|
-
"@backstage/core-app-api": "^0.1.
|
|
56
|
-
"@backstage/dev-utils": "^0.2.
|
|
57
|
-
"@backstage/test-utils": "^0.1.
|
|
54
|
+
"@backstage/cli": "^0.9.0",
|
|
55
|
+
"@backstage/core-app-api": "^0.1.21",
|
|
56
|
+
"@backstage/dev-utils": "^0.2.13",
|
|
57
|
+
"@backstage/test-utils": "^0.1.22",
|
|
58
58
|
"@testing-library/jest-dom": "^5.10.1",
|
|
59
59
|
"@testing-library/react": "^11.2.5",
|
|
60
60
|
"@testing-library/react-hooks": "^7.0.2",
|
|
@@ -67,5 +67,5 @@
|
|
|
67
67
|
"files": [
|
|
68
68
|
"dist"
|
|
69
69
|
],
|
|
70
|
-
"gitHead": "
|
|
70
|
+
"gitHead": "ddfdcd2b44dc9848cf550cea5346d5f9916a36d9"
|
|
71
71
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-022e0330.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-12477c15.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-17c9e868.esm.js","sources":["../../src/apis.ts","../../src/components/DefaultResultListItem/DefaultResultListItem.tsx","../../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","../../../../node_modules/@material-ui/icons/esm/Launch.js","../../src/components/SearchResult/SearchResult.tsx","../../src/components/SearchResultPager/SearchResultPager.tsx","../../src/plugin.ts","../../src/components/SearchModal/SearchModal.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/SearchType/SearchType.tsx","../../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 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 { IndexableDocument } from '@backstage/search-common';\nimport { ListItem, ListItemText, Divider } from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\n\ntype Props = {\n result: IndexableDocument;\n};\n\nexport const DefaultResultListItem = ({ result }: Props) => {\n return (\n <Link to={result.location}>\n <ListItem alignItems=\"flex-start\">\n <ListItemText\n primaryTypographyProps={{ variant: 'h6' }}\n primary={result.title}\n secondary={result.text}\n />\n </ListItem>\n <Divider />\n </Link>\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","import * as React from 'react';\nimport createSvgIcon from './utils/createSvgIcon';\nexport default createSvgIcon( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M19 19H5V5h7V3H5c-1.11 0-2 .9-2 2v14c0 1.1.89 2 2 2h14c1.1 0 2-.9 2-2v-7h-2v7zM14 3v2h3.59l-9.83 9.83 1.41 1.41L19 6.41V10h2V3h-7z\"\n}), 'Launch');","/*\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","/*\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 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 SidebarSearchModal = searchPlugin.provide(\n createComponentExtension({\n name: 'SidebarSearchModal',\n component: {\n lazy: () =>\n import('./components/SidebarSearchModal').then(\n m => m.SidebarSearchModal,\n ),\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 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 React, { useEffect, useState } from 'react';\nimport {\n Dialog,\n DialogActions,\n DialogContent,\n DialogTitle,\n Divider,\n Grid,\n List,\n Paper,\n} from '@material-ui/core';\nimport { Launch } from '@material-ui/icons/';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { SearchBarBase } from '../SearchBar';\nimport { DefaultResultListItem } from '../DefaultResultListItem';\nimport { SearchResult } from '../SearchResult';\nimport { SearchContextProvider, useSearch } from '../SearchContext';\nimport { SearchResultPager } from '../SearchResultPager';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { Link } from '@backstage/core-components';\nimport { rootRouteRef } from '../../plugin';\n\nimport { useDebounce } from 'react-use';\n\nexport interface SearchModalProps {\n open?: boolean;\n toggleModal: () => void;\n}\n\nconst useStyles = makeStyles(theme => ({\n container: {\n borderRadius: 30,\n display: 'flex',\n height: '2.4em',\n },\n input: {\n flex: 1,\n },\n // Reduces default height of the modal, keeping a gap of 128px between the top and bottom of the page.\n paperFullWidth: { height: 'calc(100% - 128px)' },\n dialogActionsContainer: { padding: theme.spacing(1, 3) },\n viewResultsLink: { verticalAlign: '0.5em' },\n}));\n\nexport const Modal = ({ open = true, toggleModal }: SearchModalProps) => {\n const getSearchLink = useRouteRef(rootRouteRef);\n const classes = useStyles();\n\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), 1000, [value]);\n\n const handleQuery = (newValue: string) => {\n setValue(newValue);\n };\n\n const handleClear = () => setValue('');\n\n const handleResultClick = () => {\n toggleModal();\n handleClear();\n };\n\n const handleKeyPress = () => {\n handleResultClick();\n };\n\n return (\n <Dialog\n classes={{\n paperFullWidth: classes.paperFullWidth,\n }}\n onClose={toggleModal}\n aria-labelledby=\"search-modal-title\"\n open={open}\n fullWidth\n maxWidth=\"lg\"\n >\n <DialogTitle>\n <Paper className={classes.container}>\n <SearchBarBase\n className={classes.input}\n value={value}\n onChange={handleQuery}\n onClear={handleClear}\n />\n </Paper>\n </DialogTitle>\n <DialogContent>\n <Grid\n container\n direction=\"row-reverse\"\n justifyContent=\"flex-start\"\n alignItems=\"center\"\n >\n <Grid item>\n <Link to={`${getSearchLink()}?query=${value}`}>\n <span className={classes.viewResultsLink}>View Full Results</span>\n <Launch color=\"primary\" />\n </Link>\n </Grid>\n </Grid>\n <Divider />\n <SearchResult>\n {({ results }) => (\n <List>\n {results.map(({ document }) => (\n <div\n role=\"button\"\n tabIndex={0}\n key={`${document.location}-btn`}\n onClick={handleResultClick}\n onKeyPress={handleKeyPress}\n >\n <DefaultResultListItem\n key={document.location}\n result={document}\n />\n </div>\n ))}\n </List>\n )}\n </SearchResult>\n </DialogContent>\n <DialogActions className={classes.dialogActionsContainer}>\n <Grid container direction=\"row\">\n <Grid item xs={12}>\n <SearchResultPager />\n </Grid>\n </Grid>\n </DialogActions>\n </Dialog>\n );\n};\n\nexport const SearchModal = ({ open = true, toggleModal }: SearchModalProps) => {\n return (\n <SearchContextProvider>\n <Modal open={open} toggleModal={toggleModal} />\n </SearchContextProvider>\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 { 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 */\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 */\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":["DefaultResultListItem","useStyles","FiltersButton","Filters","React","SearchBar","SearchPage","SearchResult","makeStyles","IconButton","InputBase"],"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;;MCnCPA,0BAAwB,CAAC,CAAE,YAAoB;AAC1D,sDACG,MAAD;AAAA,IAAM,IAAI,OAAO;AAAA,kDACd,UAAD;AAAA,IAAU,YAAW;AAAA,kDAClB,cAAD;AAAA,IACE,wBAAwB,CAAE,SAAS;AAAA,IACnC,SAAS,OAAO;AAAA,IAChB,WAAW,OAAO;AAAA,oDAGrB,SAAD;AAAA;;ACfN,MAAMC,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,sDACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,kDACrB,YAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,cAAW;AAAA,IACX,SAAS;AAAA,kDAER,gBAAD,qDAED,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,sDACG,MAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,kDACtB,YAAD;AAAA,IACE,oDAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,OAAK;AAAA,IAChC,qDACG,QAAD;AAAA,MAAQ,OAAM;AAAA,MAAU,SAAS,MAAM;AAAA,OAAgB;AAAA,mDAK1D,SAAD,OACC,cAAc,KAAK,WAAW,KAAK,cAAc,UAAU,WAAW,kDACpE,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,oDAKnC,cAAc,KAAK,SAAS,kDAC1B,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,sDAC/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,yDACrB,UAAD;AAAA,IACE,UAAU,WAAW;AAAA,IACrB,OAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,KAEN,YAMV,cAAc,UAAU,SAAS,kDAC/B,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,2DAC/B,MAAD;AAAA,IAAM,gBAAc;AAAA,IAAC,OAAK;AAAA,KACvB,cAAc,UAAU,IAAI,yDAC1B,UAAD;AAAA,IACE,KAAK;AAAA,IACL,OAAK;AAAA,IACL,QAAM;AAAA,IACN,SAAS,MAAM,cAAc;AAAA,kDAE5B,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,mDAEP,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,sDAAQ,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,YAAYG,eAAM,YACtB,CAAC,MAAuC;AACtC,QAAI,YAAY,EAAE,QAAQ,SAAS;AACjC;AAAA;AAAA,KAGJ,CAAC;AAGH,QAAM,cAAcA,eAAM,YAAY,MAAM;AAC1C,aAAS;AAAA,KACR,CAAC;AAEJ,QAAM,cACJ,oDACA,aAAa,UAAU,kBAAkB,gBAAgB;AAE3D,sDACG,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,6DACG,gBAAD;AAAA,MAAgB,UAAS;AAAA,oDACtB,YAAD;AAAA,MAAY,cAAW;AAAA,MAAQ,UAAQ;AAAA,oDACpC,YAAD;AAAA,IAIN,2DACG,gBAAD;AAAA,MAAgB,UAAS;AAAA,oDACtB,YAAD;AAAA,MAAY,cAAW;AAAA,MAAQ,SAAS;AAAA,oDACrC,aAAD;AAAA,OAID,aAAa,CAAE;AAAA,OACf,YAAY,CAAE;AAAA;AAAA;MAWZC,cAAY,CAAC;AAAA,EACxB;AAAA,EACA,eAAe;AAAA,EACf;AAAA,MACW;AACX,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,sDACG,eAAD;AAAA,IACE;AAAA,IACA;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA,IACT;AAAA;AAAA;;AC1FN,MAAMJ,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,sDACG,aAAD;AAAA,IACE;AAAA,IACA,WAAS;AAAA,IACT,eAAY;AAAA,kDAEX,WAAD;AAAA,IAAW,WAAW,QAAQ;AAAA,KAAQ,OACrC,OAAO,IAAI,CAAC,UAAe;AAvFlC;AAwFQ,wDAAC,kBAAD;AAAA,MACE,KAAK;AAAA,MACL,sDACG,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,sDACG,aAAD;AAAA,IACE;AAAA,IACA,SAAQ;AAAA,IACR,WAAS;AAAA,IACT,eAAY;AAAA,kDAEX,YAAD;AAAA,IAAY,WAAW,QAAQ;AAAA,IAAO,QAAO;AAAA,KAC1C,oDAEF,QAAD;AAAA,IACE,SAAQ;AAAA,IACR,OAAO,QAAQ,SAAS;AAAA,IACxB,UAAU;AAAA,kDAET,UAAD;AAAA,IAAU,OAAM;AAAA,kDACb,MAAD,MAAI,SAEL,OAAO,IAAI,CAAC,uDACV,UAAD;AAAA,IAAU,KAAK;AAAA,IAAO;AAAA,KACnB;AAAA;MAQP,eAAe,CAAC,CAAE,WAAW,YAAY,wDAC5C,SAAD;AAAA,KAAa;AAAA;AAGf,aAAa,WAAW,CAAC,uDACtB,cAAD;AAAA,KAAkB;AAAA,EAAO,WAAW;AAAA;AAGtC,aAAa,SAAS,CAAC,uDACpB,cAAD;AAAA,KAAkB;AAAA,EAAO,WAAW;AAAA;MAShC,mBAAmB;;ACtLzB,aAAe,aAAa,eAAe,KAAK,CAAC,aAAa,CAAC,MAAM,EAAE;AACvE,EAAE,CAAC,EAAE,oIAAoI;AACzI,CAAC,CAAC,EAAE,QAAQ,CAAC;;MCyBA,wBAAwB,CAAC,CAAE,cAAsB;AAC5D,QAAM;AAAA,IACJ,QAAQ,CAAE,SAAS,OAAO;AAAA,MACxB;AAEJ,MAAI,SAAS;AACX,wDAAQ,UAAD;AAAA;AAET,MAAI,OAAO;AACT,wDACG,oBAAD;AAAA,MACE,OAAM;AAAA,MACN;AAAA;AAAA;AAKN,MAAI,iCAAQ,QAAQ,SAAQ;AAC1B,wDAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,MAAO,OAAM;AAAA;AAAA;AAG1C,qFAAU,SAAS,CAAE,SAAS,MAAM;AAAA;;AC5BtC,MAAMA,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,sDACG,OAAD;AAAA,IAAK,eAAY;AAAA,IAAwB,WAAW,QAAQ;AAAA,kDACzD,QAAD;AAAA,IACE,cAAW;AAAA,IACX,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,IACT,wDAAY,kBAAD;AAAA,IACX,MAAK;AAAA,KACN,sDAIA,QAAD;AAAA,IACE,cAAW;AAAA,IACX,UAAU,CAAC;AAAA,IACX,SAAS;AAAA,IACT,sDAAU,qBAAD;AAAA,IACT,MAAK;AAAA,KACN;AAAA;;MC9BM,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;MAIDK,eAAa,aAAa,QACrC,wBAAwB;AAAA,EACtB,MAAM;AAAA,EACN,WAAW,MAAa,kCAA2B,KAAK,OAAK,EAAE;AAAA,EAC/D,YAAY;AAAA;MAUH,iBAAiB,aAAa,QACzC,wBAAwB;AAAA,EACtB,MAAM;AAAA,EACN,WAAW,MAAa,kCAA2B,KAAK,OAAK,EAAE;AAAA,EAC/D,YAAY;AAAA;AAIS,aAAa,QACpC,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MAAa,kCAA0B,KAAK,OAAK,EAAE;AAAA;AAAA;MAWlD,gBAAgB,aAAa,QACxC,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MAAa,kCAA0B,KAAK,OAAK,EAAE;AAAA;AAAA;MAKlDC,iBAAe,aAAa,QACvC,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MAAa,kCAA6B,KAAK,OAAK,EAAE;AAAA;AAAA;AAWlC,aAAa,QAC3C,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MAAa,kCAA6B,KAAK,OAAK,EAAE;AAAA;AAAA;MAKrD,qBAAqB,aAAa,QAC7C,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MACG,kCAAmC,KACxC,OAAK,EAAE;AAAA;AAAA;MAMJ,wBAAwB,aAAa,QAChD,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MACG,kCAAsC,KAC3C,OAAK,EAAE;AAAA;AAAA;MAMJ,oBAAoB,aAAa,QAC5C,yBAAyB;AAAA,EACvB,MAAM;AAAA,EACN,WAAW;AAAA,IACT,MAAM,MACG,kCAAkC,KAAK,OAAK,EAAE;AAAA;AAAA;;AC7G7D,MAAMN,cAAYO,aAAW;AAAU,EACrC,WAAW;AAAA,IACT,cAAc;AAAA,IACd,SAAS;AAAA,IACT,QAAQ;AAAA;AAAA,EAEV,OAAO;AAAA,IACL,MAAM;AAAA;AAAA,EAGR,gBAAgB,CAAE,QAAQ;AAAA,EAC1B,wBAAwB,CAAE,SAAS,MAAM,QAAQ,GAAG;AAAA,EACpD,iBAAiB,CAAE,eAAe;AAAA;MAGvB,QAAQ,CAAC,CAAE,OAAO,MAAM,iBAAoC;AACvE,QAAM,gBAAgB,YAAY;AAClC,QAAM,UAAUP;AAEhB,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,KAAM,CAAC;AAEzC,QAAM,cAAc,CAAC,aAAqB;AACxC,aAAS;AAAA;AAGX,QAAM,cAAc,MAAM,SAAS;AAEnC,QAAM,oBAAoB,MAAM;AAC9B;AACA;AAAA;AAGF,QAAM,iBAAiB,MAAM;AAC3B;AAAA;AAGF,sDACG,QAAD;AAAA,IACE,SAAS;AAAA,MACP,gBAAgB,QAAQ;AAAA;AAAA,IAE1B,SAAS;AAAA,IACT,mBAAgB;AAAA,IAChB;AAAA,IACA,WAAS;AAAA,IACT,UAAS;AAAA,kDAER,aAAD,mDACG,OAAD;AAAA,IAAO,WAAW,QAAQ;AAAA,kDACvB,eAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB;AAAA,IACA,UAAU;AAAA,IACV,SAAS;AAAA,qDAId,eAAD,mDACG,MAAD;AAAA,IACE,WAAS;AAAA,IACT,WAAU;AAAA,IACV,gBAAe;AAAA,IACf,YAAW;AAAA,kDAEV,MAAD;AAAA,IAAM,MAAI;AAAA,kDACP,MAAD;AAAA,IAAM,IAAI,GAAG,yBAAyB;AAAA,kDACnC,QAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,KAAiB,mEACzC,QAAD;AAAA,IAAQ,OAAM;AAAA,sDAInB,SAAD,oDACCM,uBAAD,MACG,CAAC,CAAE,0DACD,MAAD,MACG,QAAQ,IAAI,CAAC,CAAE,2DACb,OAAD;AAAA,IACE,MAAK;AAAA,IACL,UAAU;AAAA,IACV,KAAK,GAAG,SAAS;AAAA,IACjB,SAAS;AAAA,IACT,YAAY;AAAA,kDAEXP,yBAAD;AAAA,IACE,KAAK,SAAS;AAAA,IACd,QAAQ;AAAA,wDAQrB,eAAD;AAAA,IAAe,WAAW,QAAQ;AAAA,kDAC/B,MAAD;AAAA,IAAM,WAAS;AAAA,IAAC,WAAU;AAAA,kDACvB,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,kDACZ,mBAAD;AAAA;MAQC,cAAc,CAAC,CAAE,OAAO,MAAM,iBAAoC;AAC7E,sDACG,uBAAD,mDACG,OAAD;AAAA,IAAO;AAAA,IAAY;AAAA;AAAA;;ACtIzB,MAAMC,cAAYO,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,UAAUP;AAEhB,sDACG,OAAD;AAAA,IACE,WAAU;AAAA,IACV,UAAU,OAAK,aAAa;AAAA,IAC5B,WAAW,QAAQ;AAAA,kDAElBQ,cAAD;AAAA,IAAY,UAAQ;AAAA,IAAC,MAAK;AAAA,IAAS,cAAW;AAAA,kDAC3C,YAAD,qDAEDC,aAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,aAAY;AAAA,IACZ,OAAO;AAAA,IACP,UAAU,OAAK,aAAa;AAAA,IAC5B,YAAY,CAAE,cAAc;AAAA,mDAE7BD,cAAD;AAAA,IAAY,cAAW;AAAA,IAAS,SAAS,MAAM;AAAA,kDAC5C,aAAD;AAAA;;AC5CR,MAAMR,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,sDACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,kDACrB,YAAD;AAAA,IACE,WAAW,QAAQ;AAAA,IACnB,cAAW;AAAA,IACX,SAAS;AAAA,kDAER,gBAAD,qDAED,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,sDACG,MAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,kDACtB,YAAD;AAAA,IACE,oDAAQ,YAAD;AAAA,MAAY,SAAQ;AAAA,OAAK;AAAA,IAChC,qDACG,QAAD;AAAA,MAAQ,OAAM;AAAA,MAAU,SAAS,MAAM;AAAA,OAAgB;AAAA,mDAK1D,SAAD,OACC,cAAc,KAAK,WAAW,KAAK,cAAc,UAAU,WAAW,kDACpE,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,oDAKnC,cAAc,KAAK,SAAS,kDAC1B,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,sDAC/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,yDACrB,UAAD;AAAA,IACE,UAAU,WAAW;AAAA,IACrB,OAAK;AAAA,IACL,KAAK;AAAA,IACL,OAAO;AAAA,KAEN,YAMV,cAAc,UAAU,SAAS,kDAC/B,aAAD,mDACG,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAY,2DAC/B,MAAD;AAAA,IAAM,gBAAc;AAAA,IAAC,OAAK;AAAA,KACvB,cAAc,UAAU,IAAI,yDAC1B,UAAD;AAAA,IACE,KAAK;AAAA,IACL,OAAK;AAAA,IACL,QAAM;AAAA,IACN,SAAS,MAAM,cAAc;AAAA,kDAE5B,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,mDAEP,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,wDACN,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,sDACG,OAAD;AAAA,IAAK,WAAW,QAAQ;AAAA,kDACrB,eAAD;AAAA,IACE;AAAA,IACA;AAAA,mDAED,SAAD;AAAA,IAAS,WAAW,QAAQ;AAAA,IAAS,aAAY;AAAA,mDAChD,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,KACZ,2DACE,YAAD;AAAA,IAAY,SAAQ;AAAA,KACjB,GAAG,oBACH,kBAAkB,IAAI,iBAAiB,4DACvC,QAAD;AAAA,IAAM,WAAW,QAAQ;AAAA,KAAa,KAAE,aAAY,MAAS,oDAG9D,YAAD;AAAA,IAAY,SAAQ;AAAA,KAAM,GAAG;AAAA;MAO1B,eAAe,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,kBAAkB,aAC7C,4BACE,OAAO,KAAK,kBAAkB,YAAY,OAAO,SAAS;AAAA;AAAA;AAAA,KAE/D;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;AA5L3B;AA6LY,+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,wDAAQ,UAAD;AAAA;AAET,MAAI,OAAO;AACT,wDACG,OAAD;AAAA,MAAO,UAAS;AAAA,OAAQ,qDAC4B,MAAM;AAAA;AAI9D,MAAI,CAAC,WAAW,QAAQ,WAAW,GAAG;AACpC,wDAAQ,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,kIAEK,MAAD;AAAA,IAAM,WAAS;AAAA,KACZ,4DACE,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,kDACZ,SAAD;AAAA,IACE,SAAS;AAAA,IACT;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,oDAIL,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI,cAAc,IAAI;AAAA,kDAC9B,OAAD;AAAA,IACE,SAAS,CAAE,QAAQ,MAAM,UAAU,IAAI,QAAQ;AAAA,IAC/C,MAAM;AAAA,IACN;AAAA,IACA,oDACG,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;;MCjQ7C,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,sDACG,MAAD;AAAA,IAAM,SAAQ;AAAA,kDACX,QAAD;AAAA,IAAQ,OAAM;AAAA,mDACb,SAAD,mDACG,MAAD;AAAA,IAAM,WAAS;AAAA,IAAC,WAAU;AAAA,kDACvB,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,kDACZ,WAAD;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,oDAGH,MAAD;AAAA,IAAM,MAAI;AAAA,IAAC,IAAI;AAAA,kDACZ,cAAD;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;MAGI,aAAa,MAAM;AAC9B,QAAM,SAAS;AAEf,sDACG,uBAAD,mDACG,YAAD,OACC,uDAAW,kBAAD;AAAA;;AC/DjB,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,sDACG,aAAD;AAAA,IACE;AAAA,IACA,SAAQ;AAAA,IACR,WAAS;AAAA,IACT,eAAY;AAAA,kDAEX,YAAD;AAAA,IAAY,WAAW,QAAQ;AAAA,IAAO,QAAO;AAAA,KAC1C,oDAEF,QAAD;AAAA,IACE,UAAQ;AAAA,IACR,SAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,IACV,aAAY;AAAA,IACZ,aAAa,2DACV,OAAD;AAAA,MAAK,WAAW,QAAQ;AAAA,OACpB,SAAsB,IAAI,wDACzB,MAAD;AAAA,MACE,KAAK;AAAA,MACL,OAAO;AAAA,MACP,WAAW,QAAQ;AAAA,MACnB,MAAK;AAAA;AAAA,KAMZ,OAAO,IAAI,CAAC,uDACV,UAAD;AAAA,IAAU,KAAK;AAAA,IAAO;AAAA,kDACnB,UAAD;AAAA,IAAU,SAAS,MAAM,QAAQ,SAAS;AAAA,mDACzC,cAAD;AAAA,IAAc,SAAS;AAAA;AAAA;;MCnFtB,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,sDAAQ,oBAAD;AAAA,IAAoB,UAAU;AAAA,IAAc,IAAG;AAAA;AAAA;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-3b720a86.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index-597d3990.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;"}
|