@techdocs/cli 1.10.7-next.1 → 1.10.7

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.
Files changed (82) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/embedded-app/.config-schema.json +64 -31
  3. package/dist/embedded-app/index.html +1 -1
  4. package/dist/embedded-app/index.html.tmpl +1 -1
  5. package/dist/embedded-app/static/123.5e36a0db.chunk.js +2 -0
  6. package/dist/embedded-app/static/123.5e36a0db.chunk.js.map +1 -0
  7. package/dist/embedded-app/static/1659.76caecab.chunk.js +2 -0
  8. package/dist/embedded-app/static/1659.76caecab.chunk.js.map +1 -0
  9. package/dist/embedded-app/static/1733.d8004241.chunk.js +2 -0
  10. package/dist/embedded-app/static/1733.d8004241.chunk.js.map +1 -0
  11. package/dist/embedded-app/static/1749.3ab65683.chunk.js +2 -0
  12. package/dist/embedded-app/static/1749.3ab65683.chunk.js.map +1 -0
  13. package/dist/embedded-app/static/1994.78304f99.chunk.js +2 -0
  14. package/dist/embedded-app/static/1994.78304f99.chunk.js.map +1 -0
  15. package/dist/embedded-app/static/2295.a94805e5.chunk.js +5 -0
  16. package/dist/embedded-app/static/2295.a94805e5.chunk.js.map +1 -0
  17. package/dist/embedded-app/static/{3554.0ce35bc3.chunk.js → 3554.d745ad43.chunk.js} +2 -2
  18. package/dist/embedded-app/static/{3554.0ce35bc3.chunk.js.map → 3554.d745ad43.chunk.js.map} +1 -1
  19. package/dist/embedded-app/static/{4384.ae7b53b0.chunk.js → 4384.dc692f4f.chunk.js} +2 -2
  20. package/dist/embedded-app/static/{4384.ae7b53b0.chunk.js.map → 4384.dc692f4f.chunk.js.map} +1 -1
  21. package/dist/embedded-app/static/4587.85b7cf82.chunk.js +2 -0
  22. package/dist/embedded-app/static/4587.85b7cf82.chunk.js.map +1 -0
  23. package/dist/embedded-app/static/4648.e939339d.chunk.js +2 -0
  24. package/dist/embedded-app/static/4648.e939339d.chunk.js.map +1 -0
  25. package/dist/embedded-app/static/6138.d8ae40ee.chunk.js +2 -0
  26. package/dist/embedded-app/static/6138.d8ae40ee.chunk.js.map +1 -0
  27. package/dist/embedded-app/static/7203.1bd24814.chunk.js +2 -0
  28. package/dist/embedded-app/static/7203.1bd24814.chunk.js.map +1 -0
  29. package/dist/embedded-app/static/{7226.9f87f67d.chunk.js → 7226.bb48ee34.chunk.js} +2 -2
  30. package/dist/embedded-app/static/{7226.9f87f67d.chunk.js.map → 7226.bb48ee34.chunk.js.map} +1 -1
  31. package/dist/embedded-app/static/{8461.d5fe0648.chunk.js → 8461.0c3f2ac0.chunk.js} +3 -3
  32. package/dist/embedded-app/static/{8461.d5fe0648.chunk.js.map → 8461.0c3f2ac0.chunk.js.map} +1 -1
  33. package/dist/embedded-app/static/{8877.3f864531.chunk.js → 8877.a7ffabd9.chunk.js} +2 -2
  34. package/dist/embedded-app/static/{8877.3f864531.chunk.js.map → 8877.a7ffabd9.chunk.js.map} +1 -1
  35. package/dist/embedded-app/static/9050.69b458a6.chunk.js +2 -0
  36. package/dist/embedded-app/static/9050.69b458a6.chunk.js.map +1 -0
  37. package/dist/embedded-app/static/9230.23c1d5e0.chunk.js +2 -0
  38. package/dist/embedded-app/static/9230.23c1d5e0.chunk.js.map +1 -0
  39. package/dist/embedded-app/static/{main.161a9ecc.css → main.0657d08d.css} +2 -2
  40. package/dist/embedded-app/static/{main.161a9ecc.css.map → main.0657d08d.css.map} +1 -1
  41. package/dist/embedded-app/static/main.c9b00fd0.js +523 -0
  42. package/dist/embedded-app/static/main.c9b00fd0.js.map +1 -0
  43. package/dist/embedded-app/static/{module-react-aria-components.67232dc3.js → module-react-aria-components.c61f9ab4.js} +2 -2
  44. package/dist/embedded-app/static/{module-react-aria-components.67232dc3.js.map → module-react-aria-components.c61f9ab4.js.map} +1 -1
  45. package/dist/embedded-app/static/module-zod.b3376822.js +38 -0
  46. package/dist/embedded-app/static/module-zod.b3376822.js.map +1 -0
  47. package/dist/embedded-app/static/{runtime.c39b96cc.js → runtime.9896d1d9.js} +2 -2
  48. package/dist/embedded-app/static/{runtime.c39b96cc.js.map → runtime.9896d1d9.js.map} +1 -1
  49. package/dist/embedded-app/static/vendor.ff5541f5.js +6 -0
  50. package/dist/embedded-app/static/vendor.ff5541f5.js.map +1 -0
  51. package/dist/package.json.cjs.js +1 -1
  52. package/package.json +7 -7
  53. package/dist/embedded-app/static/123.97a62a60.chunk.js +0 -2
  54. package/dist/embedded-app/static/123.97a62a60.chunk.js.map +0 -1
  55. package/dist/embedded-app/static/1659.7dd5287b.chunk.js +0 -2
  56. package/dist/embedded-app/static/1659.7dd5287b.chunk.js.map +0 -1
  57. package/dist/embedded-app/static/1733.14c06ac4.chunk.js +0 -2
  58. package/dist/embedded-app/static/1733.14c06ac4.chunk.js.map +0 -1
  59. package/dist/embedded-app/static/1749.745aaeeb.chunk.js +0 -2
  60. package/dist/embedded-app/static/1749.745aaeeb.chunk.js.map +0 -1
  61. package/dist/embedded-app/static/1994.1f294712.chunk.js +0 -2
  62. package/dist/embedded-app/static/1994.1f294712.chunk.js.map +0 -1
  63. package/dist/embedded-app/static/2295.765b9f2e.chunk.js +0 -5
  64. package/dist/embedded-app/static/2295.765b9f2e.chunk.js.map +0 -1
  65. package/dist/embedded-app/static/4587.bf73bd77.chunk.js +0 -2
  66. package/dist/embedded-app/static/4587.bf73bd77.chunk.js.map +0 -1
  67. package/dist/embedded-app/static/4648.bd152b54.chunk.js +0 -2
  68. package/dist/embedded-app/static/4648.bd152b54.chunk.js.map +0 -1
  69. package/dist/embedded-app/static/6138.2560a5ba.chunk.js +0 -2
  70. package/dist/embedded-app/static/6138.2560a5ba.chunk.js.map +0 -1
  71. package/dist/embedded-app/static/7203.1ec93f6f.chunk.js +0 -2
  72. package/dist/embedded-app/static/7203.1ec93f6f.chunk.js.map +0 -1
  73. package/dist/embedded-app/static/9050.bab0c5db.chunk.js +0 -2
  74. package/dist/embedded-app/static/9050.bab0c5db.chunk.js.map +0 -1
  75. package/dist/embedded-app/static/9230.b3e5d612.chunk.js +0 -2
  76. package/dist/embedded-app/static/9230.b3e5d612.chunk.js.map +0 -1
  77. package/dist/embedded-app/static/main.cb460d15.js +0 -523
  78. package/dist/embedded-app/static/main.cb460d15.js.map +0 -1
  79. package/dist/embedded-app/static/module-zod.dd7f5a90.js +0 -2
  80. package/dist/embedded-app/static/module-zod.dd7f5a90.js.map +0 -1
  81. package/dist/embedded-app/static/vendor.65e7f165.js +0 -6
  82. package/dist/embedded-app/static/vendor.65e7f165.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"static/8461.d5fe0648.chunk.js","sources":["webpack://techdocs-cli-embedded-app/../../node_modules/@material-ui/icons/Share.js","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyStateImage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyState.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/FavoriteToggle/FavoriteToggle.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/ClosedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/OpenedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/Select.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Filters.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/TableLoadingBody.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Table.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/HeaderLabel/HeaderLabel.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/entityPresentationSnapshot.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogAutocomplete/CatalogAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFetchEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useEntityListProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useStarredEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/utils/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/plugin.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/plugin/Plugin.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/EntityPageDocs.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/hooks/useTechDocsLocation.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/Router.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/DocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/OffsetPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/CursorPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/EntityListDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/actions.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/SubvalueCell.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/columns.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/DefaultTechDocsHome.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsIndexPage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Page/PageWithHeader.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPicker.tsx","webpack://techdocs-cli-embedded-app/../../node_modules/@material-ui/lab/esm/Skeleton/Skeleton.js","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx","webpack://techdocs-cli-embedded-app/../../plugins/auth-react/src/components/CookieAuthRefreshProvider/CookieAuthRefreshProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/auth-react/src/hooks/useCookieAuthRefresh/useCookieAuthRefresh.tsx","webpack://techdocs-cli-embedded-app/../../node_modules/@react-hookz/web/src/useAsync/index.js","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPage/useExternalRedirect.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/translation.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchBar/SearchBar.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearch.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx"],"sourcesContent":["\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z\"\n}), 'Share');\n\nexports.default = _default;","/*\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 missingAnnotation from './assets/missingAnnotation.svg';\nimport noInformation from './assets/noInformation.svg';\nimport createComponent from './assets/createComponent.svg';\nimport noBuild from './assets/noBuild.svg';\nimport { makeStyles } from '@material-ui/core/styles';\n\ntype Props = {\n missing: 'field' | 'info' | 'content' | 'data';\n};\n\n/** @public */\nexport type EmptyStateImageClassKey = 'generalImg';\n\nconst useStyles = makeStyles(\n {\n generalImg: {\n width: '95%',\n zIndex: 2,\n position: 'relative',\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, 15%)',\n },\n },\n { name: 'BackstageEmptyStateImage' },\n);\n\n/** @public */\nexport const EmptyStateImage = ({ missing }: Props) => {\n const classes = useStyles();\n switch (missing) {\n case 'field':\n return (\n <img\n src={missingAnnotation}\n className={classes.generalImg}\n alt=\"annotation is missing\"\n />\n );\n case 'info':\n return (\n <img\n src={noInformation}\n alt=\"no Information\"\n className={classes.generalImg}\n />\n );\n case 'content':\n return (\n <img\n src={createComponent}\n alt=\"create Component\"\n className={classes.generalImg}\n />\n );\n case 'data':\n return (\n <img src={noBuild} alt=\"no Build\" className={classes.generalImg} />\n );\n default:\n return null;\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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { EmptyStateImage } from './EmptyStateImage';\n\n/** @public */\nexport type EmptyStateClassKey = 'root' | 'action' | 'imageContainer';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2, 0, 0, 0),\n },\n action: {\n marginTop: theme.spacing(2),\n },\n imageContainer: {\n position: 'relative',\n },\n }),\n { name: 'BackstageEmptyState' },\n);\n\ntype Props = {\n title: string;\n description?: string | JSX.Element;\n missing: 'field' | 'info' | 'content' | 'data' | { customImage: JSX.Element };\n action?: JSX.Element;\n};\n\n/**\n * Various placeholder views for empty state pages\n *\n * @public\n *\n */\nexport function EmptyState(props: Props) {\n const { title, description, missing, action } = props;\n const classes = useStyles();\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"space-around\"\n alignItems=\"flex-start\"\n className={classes.root}\n spacing={2}\n >\n <Grid item xs={12} md={6}>\n <Grid container direction=\"column\">\n <Grid item xs>\n <Typography variant=\"h5\">{title}</Typography>\n </Grid>\n <Grid item xs>\n <Typography variant=\"body1\">{description}</Typography>\n </Grid>\n <Grid item xs className={classes.action}>\n {action}\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={12} md={6} className={classes.imageContainer}>\n {typeof missing === 'string' ? (\n <EmptyStateImage missing={missing} />\n ) : (\n missing.customImage\n )}\n </Grid>\n </Grid>\n );\n}\n","/*\n * Copyright 2024 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 { ComponentProps } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { StarIcon, UnstarredIcon } from '../../icons';\n\nconst useStyles = makeStyles<Theme>(\n () => ({\n icon: {\n color: '#f3ba37',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n iconBorder: {\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n }),\n { name: 'BackstageFavoriteToggleIcon' },\n);\n\n/**\n * @public\n */\nexport type FavoriteToggleIconClassKey = 'icon' | 'iconBorder';\n\n/**\n * Icon used in FavoriteToggle component.\n *\n * Can be used independently, useful when used as {@link @material-table/core#MaterialTableProps.actions} in {@link @material-table/core#MaterialTable}\n *\n * @public\n */\nexport function FavoriteToggleIcon(props: { isFavorite: boolean }) {\n const { isFavorite } = props;\n const classes = useStyles();\n\n return (\n <Typography\n component=\"span\"\n className={isFavorite ? classes.icon : classes.iconBorder}\n >\n {isFavorite ? <StarIcon /> : <UnstarredIcon />}\n </Typography>\n );\n}\n\n/**\n * Props for the {@link FavoriteToggle} component.\n *\n * @public\n */\nexport type FavoriteToggleProps = ComponentProps<typeof IconButton> & {\n id: string;\n title: string;\n isFavorite: boolean;\n onToggle: (value: boolean) => void;\n};\n\n/**\n * Toggle encapsulating logic for marking something as favorite,\n * primarily used in various instances of entity lists and cards but can be used elsewhere.\n *\n * This component can only be used in as a controlled toggle and does not keep internal state.\n *\n * @public\n */\nexport function FavoriteToggle(props: FavoriteToggleProps) {\n const {\n id,\n title,\n isFavorite: value,\n onToggle: onChange,\n ...iconButtonProps\n } = props;\n return (\n <Tooltip id={id} title={title}>\n <IconButton\n aria-label={title}\n id={id}\n onClick={() => onChange(!value)}\n color=\"inherit\"\n {...iconButtonProps}\n >\n <FavoriteToggleIcon isFavorite={value} />\n </IconButton>\n </Tooltip>\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 { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\n/** @public */\nexport type ClosedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageClosedDropdown' },\n);\n\nconst ClosedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M7.5 8L6 9.5L12.0703 15.5703L18.1406 9.5L16.6406 8L12.0703 12.5703L7.5 8Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default ClosedDropdown;\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 { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\nexport type OpenedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageOpenedDropdown' },\n);\n\nconst OpenedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M16.5 16L18 14.5L11.9297 8.42969L5.85938 14.5L7.35938 16L11.9297 11.4297L16.5 16Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default OpenedDropdown;\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 Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport Chip from '@material-ui/core/Chip';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputBase from '@material-ui/core/InputBase';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Select from '@material-ui/core/Select';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport { ChangeEvent, useEffect, useState } from 'react';\n\nimport ClosedDropdown from './static/ClosedDropdown';\nimport OpenedDropdown from './static/OpenedDropdown';\n\n/** @public */\nexport type SelectInputBaseClassKey = 'root' | 'input';\n\nconst BootstrapInput = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {\n 'label + &': {\n marginTop: theme.spacing(3),\n },\n '&.Mui-focused > div[role=button]': {\n borderColor: theme.palette.primary.main,\n },\n },\n input: {\n borderRadius: theme.shape.borderRadius,\n position: 'relative',\n backgroundColor: theme.palette.background.paper,\n border: '1px solid #ced4da',\n fontSize: theme.typography.body1.fontSize,\n padding: theme.spacing(1.25, 3.25, 1.25, 1.5),\n transition: theme.transitions.create(['border-color', 'box-shadow']),\n '&:focus': {\n background: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n },\n },\n }),\n { name: 'BackstageSelectInputBase' },\n)(InputBase);\n\n/** @public */\nexport type SelectClassKey =\n | 'formControl'\n | 'label'\n | 'chips'\n | 'chip'\n | 'checkbox'\n | 'root';\n\nconst useStyles = makeStyles(\n (theme: Theme) =>\n createStyles({\n formControl: {\n margin: theme.spacing(1, 0),\n },\n label: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n formLabel: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n },\n chip: {\n margin: 2,\n },\n checkbox: {},\n\n root: {\n display: 'flex',\n flexDirection: 'column',\n },\n }),\n { name: 'BackstageSelect' },\n);\n\n/** @public */\nexport type SelectItem = {\n label: string;\n value: string | number;\n};\n\n/** @public */\nexport type SelectedItems = string | string[] | number | number[];\n\nexport type SelectProps = {\n multiple?: boolean;\n items: SelectItem[];\n label: string;\n placeholder?: string;\n selected?: SelectedItems;\n onChange: (arg: SelectedItems) => void;\n triggerReset?: boolean;\n native?: boolean;\n disabled?: boolean;\n margin?: 'dense' | 'none';\n 'data-testid'?: string;\n};\n\n/** @public */\nexport function SelectComponent(props: SelectProps) {\n const {\n multiple,\n items,\n label,\n placeholder,\n selected,\n onChange,\n triggerReset,\n native = false,\n disabled = false,\n margin,\n 'data-testid': dataTestId = 'select',\n } = props;\n const classes = useStyles();\n const [value, setValue] = useState<SelectedItems>(\n selected || (multiple ? [] : ''),\n );\n const [isOpen, setOpen] = useState(false);\n\n useEffect(() => {\n setValue(multiple ? [] : '');\n }, [triggerReset, multiple]);\n\n useEffect(() => {\n setValue(selected || (multiple ? [] : ''));\n }, [selected, multiple]);\n\n const handleChange = (event: ChangeEvent<{ value: unknown }>) => {\n setValue(event.target.value as SelectedItems);\n onChange(event.target.value as SelectedItems);\n };\n\n const handleOpen = (event: ChangeEvent<any>) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n setOpen(previous => {\n if (multiple && !(event.target instanceof HTMLElement)) {\n return true;\n }\n return !previous;\n });\n };\n\n const handleClose = () => {\n setOpen(false);\n };\n\n const handleDelete = (selectedValue: string | number) => () => {\n const newValue = (value as any[]).filter(chip => chip !== selectedValue);\n setValue(newValue);\n onChange(newValue);\n };\n\n return (\n <Box className={classes.root}>\n <FormControl className={classes.formControl}>\n <InputLabel className={classes.formLabel}>{label}</InputLabel>\n <Select\n aria-label={label}\n value={value}\n native={native}\n disabled={disabled}\n data-testid={dataTestId}\n displayEmpty\n multiple={multiple}\n margin={margin}\n onChange={handleChange}\n open={isOpen}\n onOpen={handleOpen}\n onClose={handleClose}\n input={<BootstrapInput />}\n label={label}\n renderValue={s =>\n multiple && (value as any[]).length !== 0 ? (\n <Box className={classes.chips}>\n {(s as string[]).map(selectedValue => {\n const item = items.find(el => el.value === selectedValue);\n return item ? (\n <Chip\n data-testid=\"chip\"\n key={item?.value}\n label={item?.label}\n clickable\n deleteIcon={\n <CancelIcon\n data-testid=\"cancel-icon\"\n onMouseDown={event => event.stopPropagation()}\n />\n }\n onDelete={handleDelete(selectedValue)}\n className={classes.chip}\n />\n ) : (\n false\n );\n })}\n </Box>\n ) : (\n <Typography>\n {(value as any[]).length === 0\n ? placeholder || ''\n : items.find(el => el.value === s)?.label}\n </Typography>\n )\n }\n IconComponent={() =>\n !isOpen ? <ClosedDropdown /> : <OpenedDropdown />\n }\n MenuProps={{\n anchorOrigin: {\n vertical: 'bottom',\n horizontal: 'left',\n },\n transformOrigin: {\n vertical: 'top',\n horizontal: 'left',\n },\n getContentAnchorEl: null,\n }}\n >\n {!!placeholder && !multiple && (\n <MenuItem value={[]}>{placeholder}</MenuItem>\n )}\n {native\n ? items &&\n items.map(item => (\n <option value={item.value} key={item.value}>\n {item.label}\n </option>\n ))\n : items &&\n items.map(item => (\n <MenuItem key={item.value} value={item.value}>\n {multiple && (\n <Checkbox\n color=\"primary\"\n checked={(value as any[]).includes(item.value) || false}\n className={classes.checkbox}\n />\n )}\n {item.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Box>\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 Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useState } from 'react';\n\nimport { Select } from '../Select';\nimport { SelectProps } from '../Select/Select';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n height: '100%',\n width: '315px',\n display: 'flex',\n flexDirection: 'column',\n marginRight: theme.spacing(3),\n },\n value: {\n fontWeight: 'bold',\n fontSize: 18,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: theme.spacing(7.5),\n justifyContent: 'space-between',\n borderBottom: `1px solid ${theme.palette.grey[500]}`,\n },\n filters: {\n display: 'flex',\n flexDirection: 'column',\n '& > *': {\n marginTop: theme.spacing(2),\n },\n },\n }),\n { name: 'BackstageTableFilters' },\n);\n\nexport type Without<T, K> = Pick<T, Exclude<keyof T, K>>;\n\nexport type Filter = {\n type: 'select' | 'multiple-select';\n element: Without<SelectProps, 'onChange'>;\n};\n\nexport type SelectedFilters = {\n [key: string]: string | string[];\n};\n\ntype Props = {\n filters: Filter[];\n selectedFilters?: SelectedFilters;\n onChangeFilters: (arg: any) => any;\n};\n\nexport const Filters = (props: Props) => {\n const classes = useFilterStyles();\n\n const { onChangeFilters } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>({\n ...props.selectedFilters,\n });\n const [reset, triggerReset] = useState(false);\n\n // Trigger re-rendering\n const handleClick = () => {\n setSelectedFilters({});\n triggerReset(el => !el);\n };\n\n useEffect(() => {\n onChangeFilters(selectedFilters);\n }, [selectedFilters, onChangeFilters]);\n\n // As material table doesn't provide a way to add a column filter tab we will make our own filter logic\n return (\n <Box className={classes.root}>\n <Box className={classes.header}>\n <Box className={classes.value}>{t('table.filter.title')}</Box>\n <Button color=\"primary\" onClick={handleClick}>\n {t('table.filter.clearAll')}\n </Button>\n </Box>\n <Box className={classes.filters}>\n {props.filters?.length &&\n props.filters.map(filter => (\n <Select\n triggerReset={reset}\n key={filter.element.label}\n {...(filter.element as SelectProps)}\n selected={selectedFilters[filter.element.label]}\n onChange={el =>\n setSelectedFilters({\n ...selectedFilters,\n [filter.element.label]: el as any,\n })\n }\n />\n ))}\n </Box>\n </Box>\n );\n};\n","/*\n * Copyright 2023 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 Box from '@material-ui/core/Box';\nimport CircularProgress from '@material-ui/core/CircularProgress';\n\n/**\n * @internal\n */\nexport function TableLoadingBody(props: { colSpan?: number }) {\n return (\n <tbody data-testid=\"loading-indicator\">\n <tr>\n <td colSpan={props.colSpan}>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '100%',\n minHeight: '15rem',\n }}\n >\n <CircularProgress size=\"5rem\" />\n </Box>\n </td>\n </tr>\n </tbody>\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 {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport MTable, {\n Column,\n Icons,\n MaterialTableProps,\n MTableBody,\n MTableHeader,\n MTableToolbar,\n Options,\n} from '@material-table/core';\nimport Box from '@material-ui/core/Box';\nimport IconButton from '@material-ui/core/IconButton';\nimport {\n makeStyles,\n Theme,\n useTheme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport AddBox from '@material-ui/icons/AddBox';\nimport ArrowUpward from '@material-ui/icons/ArrowUpward';\nimport Check from '@material-ui/icons/Check';\nimport ChevronLeft from '@material-ui/icons/ChevronLeft';\nimport ChevronRight from '@material-ui/icons/ChevronRight';\nimport Clear from '@material-ui/icons/Clear';\nimport DeleteOutline from '@material-ui/icons/DeleteOutline';\nimport Edit from '@material-ui/icons/Edit';\nimport FilterList from '@material-ui/icons/FilterList';\nimport Search from '@material-ui/icons/Search';\nimport FirstPage from '@material-ui/icons/FirstPage';\nimport LastPage from '@material-ui/icons/LastPage';\nimport Remove from '@material-ui/icons/Remove';\nimport SaveAlt from '@material-ui/icons/SaveAlt';\nimport ViewColumn from '@material-ui/icons/ViewColumn';\nimport { isEqual, transform } from 'lodash';\nimport {\n CSSProperties,\n forwardRef,\n MutableRefObject,\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { SelectProps } from '../Select/Select';\nimport { Filter, Filters, SelectedFilters, Without } from './Filters';\nimport { TableLoadingBody } from './TableLoadingBody';\n\n// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51\nconst tableIcons: Icons = {\n Add: forwardRef<SVGSVGElement>((props, ref) => (\n <AddBox {...props} ref={ref} />\n )),\n Check: forwardRef<SVGSVGElement>((props, ref) => (\n <Check {...props} ref={ref} />\n )),\n Clear: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Delete: forwardRef<SVGSVGElement>((props, ref) => (\n <DeleteOutline {...props} ref={ref} />\n )),\n DetailPanel: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n Edit: forwardRef<SVGSVGElement>((props, ref) => (\n <Edit {...props} ref={ref} />\n )),\n Export: forwardRef<SVGSVGElement>((props, ref) => (\n <SaveAlt {...props} ref={ref} />\n )),\n Filter: forwardRef<SVGSVGElement>((props, ref) => (\n <FilterList {...props} ref={ref} />\n )),\n FirstPage: forwardRef<SVGSVGElement>((props, ref) => (\n <FirstPage {...props} ref={ref} />\n )),\n LastPage: forwardRef<SVGSVGElement>((props, ref) => (\n <LastPage {...props} ref={ref} />\n )),\n NextPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n PreviousPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronLeft {...props} ref={ref} />\n )),\n ResetSearch: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Search: forwardRef<SVGSVGElement>((props, ref) => (\n <Search {...props} ref={ref} />\n )),\n SortArrow: forwardRef<SVGSVGElement>((props, ref) => (\n <ArrowUpward {...props} ref={ref} />\n )),\n ThirdStateCheck: forwardRef<SVGSVGElement>((props, ref) => (\n <Remove {...props} ref={ref} />\n )),\n ViewColumn: forwardRef<SVGSVGElement>((props, ref) => (\n <ViewColumn {...props} ref={ref} />\n )),\n};\n\n// TODO: Material table might already have such a function internally that we can use?\nfunction extractValueByField(data: any, field: string): any | undefined {\n const path = field.split('.');\n let value = data[path[0]];\n\n for (let i = 1; i < path.length; ++i) {\n if (value === undefined) {\n return value;\n }\n\n const f = path[i];\n value = value[f];\n }\n\n return value;\n}\n\nexport type TableHeaderClassKey = 'header';\n\nconst StyledMTableHeader = withStyles(\n theme => ({\n header: {\n padding: theme.spacing(1, 2, 1, 2.5),\n borderTop: `1px solid ${theme.palette.grey.A100}`,\n borderBottom: `1px solid ${theme.palette.grey.A100}`,\n // withStyles hasn't a generic overload for theme\n fontWeight: theme.typography.fontWeightBold,\n position: 'static',\n wordBreak: 'normal',\n textTransform: 'uppercase',\n },\n }),\n { name: 'BackstageTableHeader' },\n)(MTableHeader);\n\nexport type TableToolbarClassKey = 'root' | 'title' | 'searchField';\n\nconst StyledMTableToolbar = withStyles(\n theme => ({\n root: {\n padding: theme.spacing(3, 0, 2.5, 2.5),\n },\n title: {\n '& > h6': {\n fontWeight: theme.typography.fontWeightBold,\n },\n },\n searchField: {\n paddingRight: theme.spacing(2),\n },\n }),\n { name: 'BackstageTableToolbar' },\n)(MTableToolbar);\n\n/** @public */\nexport type FiltersContainerClassKey = 'root' | 'filterControls' | 'title';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n },\n filterControls: {\n display: 'flex',\n alignItems: 'center',\n },\n title: {\n fontWeight: theme.typography.fontWeightBold,\n fontSize: 18,\n whiteSpace: 'nowrap',\n },\n }),\n { name: 'BackstageTableFiltersContainer' },\n);\n\nexport type TableClassKey = 'root';\n\nconst useTableStyles = makeStyles(\n () => ({\n root: {\n display: 'flex',\n alignItems: 'start',\n },\n }),\n { name: 'BackstageTable' },\n);\n\nfunction convertColumns<T extends object>(\n columns: TableColumn<T>[],\n theme: Theme,\n): TableColumn<T>[] {\n return columns.map(column => {\n const headerStyle: CSSProperties = column.headerStyle ?? {};\n\n let cellStyle = column.cellStyle || {};\n\n if (column.highlight) {\n headerStyle.color = theme.palette.textContrast;\n\n if (typeof cellStyle === 'object') {\n (cellStyle as CSSProperties).fontWeight =\n theme.typography.fontWeightBold;\n } else {\n const cellStyleFn = cellStyle as (\n data: any,\n rowData: T,\n column?: Column<T>,\n ) => CSSProperties;\n cellStyle = (data, rowData, rowColumn) => {\n const style = cellStyleFn(data, rowData, rowColumn);\n return { ...style, fontWeight: theme.typography.fontWeightBold };\n };\n }\n }\n\n return {\n ...column,\n headerStyle,\n cellStyle,\n };\n });\n}\n\nfunction removeDefaultValues(state: any, defaultState: any): any {\n return transform(state, (result, value, key) => {\n if (!isEqual(value, defaultState[key])) {\n result[key] = value;\n }\n });\n}\n\nconst defaultInitialState = {\n search: '',\n filtersOpen: false,\n filters: {},\n};\n\nexport interface TableColumn<T extends object = {}> extends Column<T> {\n highlight?: boolean;\n width?: string;\n}\n\nexport type TableFilter = {\n column: string;\n type: 'select' | 'multiple-select';\n};\n\nexport type TableState = {\n search?: string;\n filtersOpen?: boolean;\n filters?: SelectedFilters;\n};\n\nexport interface TableProps<T extends object = {}>\n extends MaterialTableProps<T> {\n columns: TableColumn<T>[];\n subtitle?: string;\n filters?: TableFilter[];\n initialState?: TableState;\n emptyContent?: ReactNode;\n isLoading?: boolean;\n onStateChange?: (state: TableState) => any;\n}\n\nexport interface TableOptions<T extends object = {}> extends Options<T> {}\n\nexport function TableToolbar(toolbarProps: {\n toolbarRef: MutableRefObject<any>;\n setSearch: (value: string) => void;\n onSearchChanged: (value: string) => void;\n toggleFilters: () => void;\n hasFilters: boolean;\n selectedFiltersLength: number;\n}) {\n const {\n toolbarRef,\n setSearch,\n hasFilters,\n selectedFiltersLength,\n toggleFilters,\n } = toolbarProps;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const filtersClasses = useFilterStyles();\n const onSearchChanged = useCallback(\n (searchText: string) => {\n toolbarProps.onSearchChanged(searchText);\n setSearch(searchText);\n },\n [toolbarProps, setSearch],\n );\n\n if (hasFilters) {\n return (\n <Box className={filtersClasses.root}>\n <Box className={filtersClasses.filterControls}>\n <IconButton onClick={toggleFilters} aria-label=\"filter list\">\n <FilterList />\n </IconButton>\n <Typography className={filtersClasses.title}>\n {t('table.filter.title')} ({selectedFiltersLength})\n </Typography>\n </Box>\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n </Box>\n );\n }\n\n return (\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n );\n}\n\n/**\n * @public\n */\nexport function Table<T extends object = {}>(props: TableProps<T>) {\n const {\n data,\n columns,\n emptyContent,\n options,\n title,\n subtitle,\n localization,\n filters,\n initialState,\n onStateChange,\n components,\n isLoading: loading,\n style,\n ...restProps\n } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const tableClasses = useTableStyles();\n\n const theme = useTheme();\n\n const calculatedInitialState = { ...defaultInitialState, ...initialState };\n\n const [filtersOpen, setFiltersOpen] = useState(\n calculatedInitialState.filtersOpen,\n );\n const toggleFilters = useCallback(\n () => setFiltersOpen(v => !v),\n [setFiltersOpen],\n );\n\n const [selectedFilters, setSelectedFilters] = useState(\n calculatedInitialState.filters,\n );\n\n const [search, setSearch] = useState(calculatedInitialState.search);\n\n useEffect(() => {\n if (onStateChange) {\n const state = removeDefaultValues(\n {\n search,\n filtersOpen,\n filters: selectedFilters,\n },\n defaultInitialState,\n );\n\n onStateChange(state);\n }\n }, [search, filtersOpen, selectedFilters, onStateChange]);\n\n const getFieldByTitle = useCallback(\n (titleValue: string | keyof T) =>\n columns.find(el => el.title === titleValue)?.field,\n [columns],\n );\n\n const tableData = useMemo(() => {\n if (typeof data === 'function' || !selectedFilters) {\n return data;\n }\n\n const selectedFiltersArray = Object.values(selectedFilters);\n if (data && selectedFiltersArray.flat().length) {\n const newData = (data as any[]).filter(\n el =>\n !!Object.entries(selectedFilters)\n .filter(([, value]) => !!(value as { length?: number }).length)\n .every(([key, filterValue]) => {\n const fieldValue = extractValueByField(\n el,\n getFieldByTitle(key) as string,\n );\n\n if (Array.isArray(fieldValue) && Array.isArray(filterValue)) {\n return fieldValue.some(v => filterValue.includes(v));\n } else if (Array.isArray(fieldValue)) {\n return fieldValue.includes(filterValue);\n } else if (Array.isArray(filterValue)) {\n return filterValue.includes(fieldValue);\n }\n\n return fieldValue === filterValue;\n }),\n );\n return newData;\n }\n return data;\n }, [data, selectedFilters, getFieldByTitle]);\n\n const selectedFiltersLength = Object.values(selectedFilters).flat().length;\n\n const hasFilters = !!filters?.length;\n const Toolbar = useCallback(\n (toolbarProps: any /* no type for this in material-table */) => {\n return (\n <TableToolbar\n setSearch={setSearch}\n hasFilters={hasFilters}\n selectedFiltersLength={selectedFiltersLength}\n toggleFilters={toggleFilters}\n {...toolbarProps}\n />\n );\n },\n [toggleFilters, hasFilters, selectedFiltersLength, setSearch],\n );\n\n const hasNoRows = typeof data !== 'function' && data.length === 0;\n const columnCount = columns.length;\n const Body = useMemo(\n () => makeBody({ hasNoRows, emptyContent, columnCount, loading }),\n [hasNoRows, emptyContent, columnCount, loading],\n );\n\n return (\n <Box className={tableClasses.root}>\n {filtersOpen && data && typeof data !== 'function' && filters?.length && (\n <Filters\n filters={constructFilters(filters, data as any[], columns, t)}\n selectedFilters={selectedFilters}\n onChangeFilters={setSelectedFilters}\n />\n )}\n <MTable<T>\n components={{\n Header: StyledMTableHeader,\n Body,\n Toolbar,\n ...components,\n }}\n options={options}\n columns={convertColumns(columns, theme)}\n icons={tableIcons}\n title={\n <>\n <Typography variant=\"h5\" component=\"h2\">\n {title}\n </Typography>\n {subtitle && (\n <Typography color=\"textSecondary\" variant=\"body1\">\n {subtitle}\n </Typography>\n )}\n </>\n }\n data={tableData}\n style={{ width: '100%', ...style }}\n localization={{\n ...localization,\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n ...localization?.body,\n },\n pagination: {\n firstTooltip: t('table.pagination.firstTooltip'),\n labelDisplayedRows: t('table.pagination.labelDisplayedRows'),\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n lastTooltip: t('table.pagination.lastTooltip'),\n nextTooltip: t('table.pagination.nextTooltip'),\n previousTooltip: t('table.pagination.previousTooltip'),\n ...localization?.pagination,\n },\n header: {\n actions: t('table.header.actions'),\n ...localization?.header,\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.search'),\n searchTooltip: t('table.toolbar.search'),\n ...localization?.toolbar,\n },\n }}\n {...restProps}\n />\n </Box>\n );\n}\n\nTable.icons = Object.freeze(tableIcons);\n\nfunction makeBody({\n columnCount,\n emptyContent,\n hasNoRows,\n loading,\n}: {\n hasNoRows: boolean;\n emptyContent: ReactNode;\n columnCount: number;\n loading?: boolean;\n}) {\n return (bodyProps: any /* no type for this in material-table */) => {\n if (loading) {\n return <TableLoadingBody colSpan={columnCount} />;\n }\n\n if (emptyContent && hasNoRows) {\n return (\n <tbody>\n <tr>\n <td colSpan={columnCount}>{emptyContent}</td>\n </tr>\n </tbody>\n );\n }\n\n return <MTableBody {...bodyProps} />;\n };\n}\n\nfunction constructFilters<T extends object>(\n filterConfig: TableFilter[],\n dataValue: any[] | undefined,\n columns: TableColumn<T>[],\n t: TranslationFunction<typeof coreComponentsTranslationRef.T>,\n): Filter[] {\n const extractDistinctValues = (field: string | keyof T): Set<any> => {\n const distinctValues = new Set<any>();\n const addValue = (value: any) => {\n if (value !== undefined && value !== null) {\n distinctValues.add(value);\n }\n };\n\n if (dataValue) {\n dataValue.forEach(el => {\n const value = extractValueByField(\n el,\n columns.find(c => c.title === field)?.field as string,\n );\n\n if (Array.isArray(value)) {\n (value as []).forEach(addValue);\n } else {\n addValue(value);\n }\n });\n }\n\n return distinctValues;\n };\n\n const constructSelect = (\n filter: TableFilter,\n ): Without<SelectProps, 'onChange'> => {\n return {\n placeholder: t('table.filter.placeholder'),\n label: filter.column,\n multiple: filter.type === 'multiple-select',\n items: [...extractDistinctValues(filter.column)].sort().map(value => ({\n label: value,\n value,\n })),\n };\n };\n\n return filterConfig.map(filter => ({\n type: filter.type,\n element: constructSelect(filter),\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 Grid from '@material-ui/core/Grid';\nimport { alpha, makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode, PropsWithChildren } from 'react';\nimport { Link } from '../../components/Link';\n\n/** @public */\nexport type HeaderLabelClassKey = 'root' | 'label' | 'value';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n textAlign: 'left',\n },\n label: {\n color: theme.page.fontColor,\n fontWeight: theme.typography.fontWeightBold,\n letterSpacing: 0,\n fontSize: theme.typography.fontSize,\n marginBottom: theme.spacing(1) / 2,\n lineHeight: 1,\n },\n value: {\n color: alpha(theme.page.fontColor, 0.8),\n fontSize: theme.typography.fontSize,\n lineHeight: 1,\n },\n }),\n { name: 'BackstageHeaderLabel' },\n);\n\ntype HeaderLabelContentProps = PropsWithChildren<{\n value: ReactNode;\n className: string;\n typographyRootComponent?: keyof JSX.IntrinsicElements;\n}>;\n\nconst HeaderLabelContent = ({\n value,\n className,\n typographyRootComponent,\n}: HeaderLabelContentProps) => {\n return (\n <Typography\n component={\n typographyRootComponent ?? (typeof value === 'string' ? 'p' : 'span')\n }\n className={className}\n >\n {value}\n </Typography>\n );\n};\n\ntype HeaderLabelProps = {\n label: string;\n value?: HeaderLabelContentProps['value'];\n contentTypograpyRootComponent?: HeaderLabelContentProps['typographyRootComponent'];\n url?: string;\n};\n\n/**\n * Additional label to main {@link Header}\n *\n * @public\n *\n */\nexport function HeaderLabel(props: HeaderLabelProps) {\n const { label, value, url, contentTypograpyRootComponent } = props;\n const classes = useStyles();\n const content = (\n <HeaderLabelContent\n className={classes.value}\n value={value || '<Unknown>'}\n typographyRootComponent={contentTypograpyRootComponent}\n />\n );\n return (\n <Grid item>\n <Typography component=\"span\" className={classes.root}>\n <Typography className={classes.label}>{label}</Typography>\n {url ? <Link to={url}>{content}</Link> : content}\n </Typography>\n </Grid>\n );\n}\n","/*\n * Copyright 2026 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 CompoundEntityRef,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n EntityPresentationApi,\n EntityRefPresentationSnapshot,\n} from './EntityPresentationApi';\nimport { defaultEntityPresentation } from './defaultEntityPresentation';\n\n/**\n * Returns a synchronous presentation snapshot for an entity in non-React\n * contexts.\n *\n * @remarks\n *\n * This is the synchronous, non-React counterpart to\n * {@link useEntityPresentation}. It handles `Entity`, `CompoundEntityRef`,\n * and string ref inputs uniformly, using the provided\n * {@link EntityPresentationApi} when available and falling back to\n * {@link defaultEntityPresentation} otherwise.\n *\n * Because this function is synchronous, it uses cached data from the\n * presentation API (via `.snapshot`). If the entity has been seen before,\n * the snapshot will contain the full resolved title; otherwise it falls\n * back to what can be extracted from the ref alone. This is the correct\n * trade-off for sort comparators, column factories, filter callbacks, and\n * data mappers where a synchronous return value is required.\n *\n * In async contexts such as data loaders where you can `await`, prefer\n * using the {@link EntityPresentationApi} directly via\n * `forEntity().promise` for the richest possible presentation.\n *\n * @public\n * @param entityOrRef - An entity, a compound entity ref, or a string entity ref.\n * @param context - Optional context that may affect the presentation.\n * @param entityPresentationApi - Optional presentation API instance. When not\n * provided, falls back to {@link defaultEntityPresentation}.\n */\nexport function entityPresentationSnapshot(\n entityOrRef: Entity | CompoundEntityRef | string,\n context?: { defaultKind?: string; defaultNamespace?: string },\n entityPresentationApi?: EntityPresentationApi,\n): EntityRefPresentationSnapshot {\n if (entityPresentationApi) {\n const ref =\n typeof entityOrRef === 'string' || 'metadata' in entityOrRef\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n return entityPresentationApi.forEntity(ref, context).snapshot;\n }\n return defaultEntityPresentation(entityOrRef, context);\n}\n","/*\n * Copyright 2024 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 Box from '@material-ui/core/Box';\nimport Typography, { TypographyProps } from '@material-ui/core/Typography';\nimport Paper, { PaperProps } from '@material-ui/core/Paper';\nimport Popper, { PopperProps } from '@material-ui/core/Popper';\nimport TextField, { OutlinedTextFieldProps } from '@material-ui/core/TextField';\nimport Grow from '@material-ui/core/Grow';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport { ReactNode, useCallback } from 'react';\nimport { merge } from 'lodash';\nimport classNames from 'classnames';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n margin: theme.spacing(1, 0),\n },\n label: {\n position: 'relative',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '& > span': {\n top: 0,\n left: 0,\n position: 'absolute',\n },\n },\n }),\n { name: 'BackstageAutocomplete' },\n);\n\nconst BootstrapAutocomplete = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {},\n paper: {\n margin: 0,\n },\n hasClearIcon: {},\n hasPopupIcon: {},\n focused: {},\n inputRoot: {\n marginTop: 24,\n backgroundColor: theme.palette.background.paper,\n '$root$hasClearIcon$hasPopupIcon &': {\n paddingBlock: theme.spacing(0.75),\n paddingInlineStart: theme.spacing(0.75),\n },\n '$root$focused &': {\n outline: 'none',\n },\n '$root &:hover > fieldset': {\n borderColor: '#ced4da',\n },\n '$root$focused & > fieldset': {\n borderWidth: 1,\n borderColor: theme.palette.primary.main,\n },\n },\n popupIndicator: {\n padding: 0,\n margin: 0,\n color: '#616161',\n '&:hover': {\n backgroundColor: 'unset',\n },\n '& [class*=\"MuiTouchRipple-root\"]': {\n display: 'none',\n },\n },\n endAdornment: {\n '$root$hasClearIcon$hasPopupIcon &': {\n right: 4,\n },\n },\n input: {\n '$root$hasClearIcon$hasPopupIcon &': {\n fontSize: theme.typography.body1.fontSize,\n paddingBlock: theme.spacing(0.8125),\n },\n },\n }),\n { name: 'BackstageAutocompleteBase' },\n)(Autocomplete) as typeof Autocomplete;\n\nconst PopperComponent = (props: PopperProps) => (\n <Popper {...props} transition placement=\"bottom-start\">\n {({ TransitionProps }) => (\n <Grow {...TransitionProps} style={{ transformOrigin: '0 0 0' }}>\n <Box>{props.children as ReactNode}</Box>\n </Grow>\n )}\n </Popper>\n);\n\nconst PaperComponent = (props: PaperProps) => (\n <Paper {...props} elevation={8} />\n);\n\n/**\n * Props for {@link CatalogAutocomplete}\n *\n * @public\n */\nexport type CatalogAutocompleteProps<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n> = Omit<\n AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,\n 'PopperComponent' | 'PaperComponent' | 'popupIcon' | 'renderInput'\n> & {\n name: string;\n label?: string;\n LabelProps?: TypographyProps<'label'>;\n TextFieldProps?: Omit<OutlinedTextFieldProps, 'variant'>;\n renderInput?: AutocompleteProps<\n T,\n Multiple,\n DisableClearable,\n FreeSolo\n >['renderInput'];\n};\n\n/** @public */\nexport function CatalogAutocomplete<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n>(props: CatalogAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>) {\n const { label, name, LabelProps, TextFieldProps, ...rest } = props;\n const classes = useStyles();\n const renderInput = useCallback(\n (params: AutocompleteRenderInputParams) => (\n <TextField {...merge(params, TextFieldProps)} variant=\"outlined\" />\n ),\n [TextFieldProps],\n );\n const autocomplete = (\n <BootstrapAutocomplete\n size=\"small\"\n {...rest}\n renderInput={rest.renderInput ?? renderInput}\n popupIcon={<ExpandMoreIcon data-testid={`${name}-expand`} />}\n PaperComponent={PaperComponent}\n PopperComponent={PopperComponent}\n />\n );\n\n return (\n <Box className={classes.root}>\n {label ? (\n <Typography\n {...LabelProps}\n className={classNames(classes.label, LabelProps?.className)}\n component=\"label\"\n >\n <Box component=\"span\">{label}</Box>\n {autocomplete}\n </Typography>\n ) : (\n autocomplete\n )}\n </Box>\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 { ReactNode, useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport Drawer from '@material-ui/core/Drawer';\nimport Grid from '@material-ui/core/Grid';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { Theme, useTheme } from '@material-ui/core/styles';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport const Filters = (props: {\n children: ReactNode;\n options?: {\n drawerBreakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;\n drawerAnchor?: 'left' | 'right' | 'top' | 'bottom';\n };\n}) => {\n const isScreenSmallerThanBreakpoint = useMediaQuery(\n (theme: Theme) =>\n theme.breakpoints.down(props.options?.drawerBreakpoint ?? 'md'),\n { noSsr: true },\n );\n const theme = useTheme();\n const [filterDrawerOpen, setFilterDrawerOpen] = useState<boolean>(false);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return isScreenSmallerThanBreakpoint ? (\n <>\n <Button\n style={{ marginTop: theme.spacing(1), marginLeft: theme.spacing(1) }}\n onClick={() => setFilterDrawerOpen(true)}\n startIcon={<FilterListIcon />}\n >\n {t('catalogFilter.buttonTitle')}\n </Button>\n <Drawer\n open={filterDrawerOpen}\n onClose={() => setFilterDrawerOpen(false)}\n anchor={props.options?.drawerAnchor ?? 'left'}\n disableAutoFocus\n keepMounted\n variant=\"temporary\"\n >\n <Box m={2}>\n <Typography\n variant=\"h6\"\n component=\"h2\"\n style={{ marginBottom: theme.spacing(1) }}\n >\n {t('catalogFilter.title')}\n </Typography>\n {props.children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const Content = (props: { children: ReactNode }) => {\n return (\n <Grid item xs={12} lg={10}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const CatalogFilterLayout = (props: { children: ReactNode }) => {\n return (\n <Grid container style={{ position: 'relative' }}>\n {props.children}\n </Grid>\n );\n};\n\nCatalogFilterLayout.Filters = Filters;\nCatalogFilterLayout.Content = Content;\n","/*\n * Copyright 2022 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 Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { memo } from 'react';\n\ninterface Props {\n selected: boolean;\n value: string;\n availableOptions?: Record<string, number>;\n showCounts: boolean;\n}\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nfunction OptionCheckbox({ selected }: { selected: boolean }) {\n return <Checkbox icon={icon} checkedIcon={checkedIcon} checked={selected} />;\n}\n\nexport const EntityAutocompletePickerOption = memo((props: Props) => {\n const { selected, value, availableOptions, showCounts } = props;\n const label = showCounts ? `${value} (${availableOptions?.[value]})` : value;\n\n return (\n <FormControlLabel\n control={<OptionCheckbox selected={selected} />}\n label={label}\n onClick={event => event.preventDefault()}\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 Box from '@material-ui/core/Box';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption';\nimport {\n DefaultEntityFilters,\n useEntityList,\n} from '../../hooks/useEntityListProvider';\nimport { EntityFilter } from '../../types';\nimport { reduceBackendCatalogFilters } from '../../utils/filters';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\nimport { isEqual } from 'lodash';\n\n/** @public */\nexport type AllowedEntityFilters<T extends DefaultEntityFilters> = {\n [K in keyof T]-?: NonNullable<T[K]> extends EntityFilter & {\n values: string[];\n }\n ? K\n : never;\n}[keyof T];\n\n/** @public */\nexport type EntityAutocompletePickerProps<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n> = {\n label: string;\n name: Name;\n path: string;\n showCounts?: boolean;\n Filter: { new (values: string[]): NonNullable<T[Name]> };\n InputProps?: TextFieldProps;\n initialSelectedOptions?: string[];\n filtersForAvailableValues?: Array<keyof T>;\n hidden?: boolean;\n};\n\n/** @public */\nexport type CatalogReactEntityAutocompletePickerClassKey = 'root' | 'label';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {\n textTransform: 'none',\n fontWeight: 'bold',\n },\n },\n { name: 'CatalogReactEntityAutocompletePicker' },\n);\n\n/** @public */\nexport function EntityAutocompletePicker<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n>(props: EntityAutocompletePickerProps<T, Name>) {\n const {\n label,\n name,\n path,\n showCounts,\n Filter,\n InputProps,\n initialSelectedOptions = [],\n filtersForAvailableValues = ['kind'],\n hidden,\n } = props;\n const classes = useStyles();\n\n const {\n updateFilters,\n filters,\n queryParameters: { [name]: queryParameter },\n } = useEntityList<T>();\n\n const catalogApi = useApi(catalogApiRef);\n const availableValuesFilters = filtersForAvailableValues.map(\n f => filters[f] as EntityFilter | undefined,\n );\n const { value: availableValues } = useAsync(async () => {\n const facet = path;\n const { facets } = await catalogApi.getEntityFacets({\n facets: [facet],\n filter: reduceBackendCatalogFilters(\n availableValuesFilters.filter(Boolean) as EntityFilter[],\n ),\n });\n\n return Object.fromEntries(\n facets[facet].map(({ value, count }) => [value, count]),\n );\n }, [...availableValuesFilters]);\n\n const queryParameters = useMemo(\n () => [queryParameter].flat().filter(Boolean) as string[],\n [queryParameter],\n );\n\n const filteredOptions = (filters[name] as unknown as { values: string[] })\n ?.values;\n\n const [selectedOptions, setSelectedOptions] = useState(\n queryParameters.length\n ? queryParameters\n : filteredOptions ?? initialSelectedOptions,\n );\n\n // Set selected options on query parameter updates; this happens at initial page load and from\n // external updates to the page location\n useEffect(() => {\n if (queryParameters.length) {\n setSelectedOptions(queryParameters);\n }\n }, [queryParameters]);\n\n const availableOptions = Object.keys(availableValues ?? {});\n const shouldAddFilter = selectedOptions.length && availableOptions.length;\n\n // Update filter value when selectedOptions change\n useEffect(() => {\n updateFilters({\n [name]: shouldAddFilter ? new Filter(selectedOptions) : undefined,\n } as Partial<T>);\n }, [name, shouldAddFilter, selectedOptions, Filter, updateFilters]);\n\n // Update selected options when filter value changes\n useEffect(() => {\n if (!shouldAddFilter) return;\n\n const newSelectedOptions = filteredOptions ?? [];\n\n // Check value is actually different (not just a different reference) to prevent selectedOptions <> filters loop\n if (!isEqual(newSelectedOptions, selectedOptions)) {\n setSelectedOptions(newSelectedOptions);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Don't re-set filter value when selectedOptions changes\n }, [filteredOptions]);\n\n const filter = filters[name];\n if (\n (filter && typeof filter === 'object' && !('values' in filter)) ||\n !availableOptions.length\n ) {\n return null;\n }\n\n return hidden ? null : (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<string, true>\n multiple\n disableCloseOnSelect\n label={label}\n name={`${String(name)}-picker`}\n options={availableOptions}\n value={selectedOptions}\n TextFieldProps={InputProps}\n onChange={(_event: object, options: string[]) =>\n setSelectedOptions(options)\n }\n renderOption={(option, { selected }) => (\n <EntityAutocompletePickerOption\n selected={selected}\n value={option}\n availableOptions={availableValues}\n showCounts={!!showCounts}\n />\n )}\n />\n </Box>\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 {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { MouseEvent, useEffect, useMemo, useState } from 'react';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityOwnerFilter } from '../../filters';\nimport { useDebouncedEffect } from '@react-hookz/web';\nimport PersonIcon from '@material-ui/icons/Person';\nimport GroupIcon from '@material-ui/icons/Group';\nimport {\n entityPresentationApiRef,\n entityPresentationSnapshot,\n} from '../../apis';\nimport { useFetchEntities } from './useFetchEntities';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\n\n/** @public */\nexport type CatalogReactEntityOwnerPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {},\n input: {},\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n },\n { name: 'CatalogReactEntityOwnerPicker' },\n);\n\n/** @public */\nexport type FixedWidthFormControlLabelClassKey = 'label' | 'root';\n\nconst FixedWidthFormControlLabel = withStyles(\n _theme => ({\n label: {\n width: '100%',\n },\n root: {\n width: '90%',\n },\n }),\n { name: 'FixedWidthFormControlLabel' },\n)(FormControlLabel);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * @public\n */\nexport type EntityOwnerPickerProps = {\n mode?: 'owners-only' | 'all';\n};\n\nfunction RenderOptionLabel(props: { entity: Entity; isSelected: boolean }) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLocaleLowerCase('en-US') === 'group';\n const { primaryTitle: title } = useEntityPresentation(props.entity);\n return (\n <Box className={classes.fullWidth}>\n <FixedWidthFormControlLabel\n className={classes.fullWidth}\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={props.isSelected}\n />\n }\n onClick={event => event.preventDefault()}\n label={\n <Tooltip title={title}>\n <Box display=\"flex\" alignItems=\"center\">\n {isGroup ? (\n <GroupIcon fontSize=\"small\" />\n ) : (\n <PersonIcon fontSize=\"small\" />\n )}\n &nbsp;\n <Box className={classes.boxLabel}>\n <Typography noWrap>{title}</Typography>\n </Box>\n </Box>\n </Tooltip>\n }\n />\n </Box>\n );\n}\n\n/** @public */\nexport const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => {\n const classes = useStyles();\n const { mode = 'owners-only' } = props || {};\n const apis = useApiHolder();\n const entityPresentationApi = apis.get(entityPresentationApiRef);\n const {\n updateFilters,\n filters,\n queryParameters: { owners: ownersParameter },\n } = useEntityList();\n\n const [text, setText] = useState('');\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const queryParamOwners = useMemo(\n () => [ownersParameter].flat().filter(Boolean) as string[],\n [ownersParameter],\n );\n\n const [selectedOwners, setSelectedOwners] = useState<string[]>(\n queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(\n () => handleFetch({ text: text.toLocaleLowerCase('en-US') }),\n [text, handleFetch],\n 250,\n );\n\n const availableOwners = value?.items || [];\n\n // Set selected owners on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamOwners.length) {\n const filter = new EntityOwnerFilter(queryParamOwners);\n setSelectedOwners(filter.values);\n }\n }, [queryParamOwners]);\n\n useEffect(() => {\n updateFilters({\n owners: selectedOwners.length\n ? new EntityOwnerFilter(selectedOwners)\n : undefined,\n });\n }, [selectedOwners, updateFilters]);\n\n if (\n ['user', 'group'].includes(\n filters.kind?.value.toLocaleLowerCase('en-US') || '',\n )\n ) {\n return null;\n }\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<Entity, true>\n label={t('entityOwnerPicker.title')}\n multiple\n disableCloseOnSelect\n loading={loading}\n options={availableOwners}\n value={selectedOwners as unknown as Entity[]}\n getOptionSelected={(o, v) => {\n if (typeof v === 'string') {\n return stringifyEntityRef(o) === v;\n }\n return o === v;\n }}\n getOptionLabel={o => {\n const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return entityPresentationSnapshot(\n entity,\n undefined,\n entityPresentationApi,\n ).primaryTitle;\n }}\n onChange={(_: object, owners) => {\n setText('');\n setSelectedOwners(\n owners.map(e => {\n const entityRef =\n typeof e === 'string' ? e : stringifyEntityRef(e);\n\n if (typeof e !== 'string') {\n cache.setEntity(e);\n }\n return entityRef;\n }),\n );\n }}\n filterOptions={x => x}\n renderOption={(entity, { selected }) => {\n return <RenderOptionLabel entity={entity} isSelected={selected} />;\n }}\n name=\"owner-picker\"\n onInputChange={(_e, inputValue) => {\n setText(inputValue);\n }}\n ListboxProps={{\n onScroll: (e: MouseEvent) => {\n const element = e.currentTarget;\n const hasReachedEnd =\n Math.abs(\n element.scrollHeight - element.clientHeight - element.scrollTop,\n ) < 1;\n\n if (hasReachedEnd && value?.cursor) {\n handleFetch({ items: value.items, cursor: value.cursor });\n }\n },\n 'data-testid': 'owner-picker-listbox',\n }}\n LabelProps={{ className: classes.label }}\n TextFieldProps={{ className: classes.input }}\n />\n </Box>\n );\n};\n","/*\n * Copyright 2023 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 { useRef } from 'react';\nimport { useFacetsEntities } from './useFacetsEntities';\nimport { useQueryEntities } from './useQueryEntities';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { useMountEffect } from '@react-hookz/web';\n\nexport function useFetchEntities({\n mode,\n initialSelectedOwnersRefs,\n}: {\n mode: 'owners-only' | 'all';\n initialSelectedOwnersRefs: string[];\n}) {\n const isOwnersOnlyMode = mode === 'owners-only';\n const queryEntitiesResponse = useQueryEntities();\n const facetsEntitiesResponse = useFacetsEntities({\n enabled: isOwnersOnlyMode,\n });\n\n const [state, handleFetch] = isOwnersOnlyMode\n ? facetsEntitiesResponse\n : queryEntitiesResponse;\n\n return [\n state,\n handleFetch,\n useSelectedOwners({\n enabled: !isOwnersOnlyMode,\n initialSelectedOwnersRefs,\n }),\n ] as const;\n}\n\n/**\n * Hook used for storing the full entity of the specified owners\n * in order to display users and group using the information contained on each entity.\n * When a component is rendered for the first time, it loads the content of the entities\n * specified by `initialSelectedOwnersRefs` and export the `getEntity` and `setEntity`\n * utilities, used to retrieve and modify the owners.\n */\nfunction useSelectedOwners({\n enabled,\n initialSelectedOwnersRefs,\n}: {\n enabled: boolean;\n initialSelectedOwnersRefs: string[];\n}) {\n const allEntities = useRef<Record<string, Entity>>({});\n const catalogApi = useApi(catalogApiRef);\n\n const [, handleFetch] = useAsyncFn(async () => {\n const initialSelectedEntities = await catalogApi.getEntitiesByRefs({\n entityRefs: initialSelectedOwnersRefs,\n });\n initialSelectedEntities.items.forEach(e => {\n if (e) {\n allEntities.current[stringifyEntityRef(e)] = e;\n }\n });\n }, []);\n\n useMountEffect(() => {\n if (enabled && initialSelectedOwnersRefs.length > 0) {\n handleFetch();\n }\n });\n\n return {\n getEntity: (entityRef: string) => allEntities.current[entityRef],\n setEntity: (entity: Entity) => {\n allEntities.current[stringifyEntityRef(entity)] = entity;\n },\n };\n}\n","/*\n * Copyright 2023 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 { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { Entity } from '@backstage/catalog-model';\n\ntype QueryEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\nexport function useQueryEntities() {\n const catalogApi = useApi(catalogApiRef);\n return useAsyncFn(\n async (\n request: { text: string } | QueryEntitiesResponse,\n options?: { limit: number },\n ): Promise<QueryEntitiesResponse> => {\n const initialRequest = request as { text: string };\n const cursorRequest = request as QueryEntitiesResponse;\n const limit = options?.limit ?? 20;\n\n if (cursorRequest.cursor) {\n const response = await catalogApi.queryEntities({\n cursor: cursorRequest.cursor,\n limit,\n });\n return {\n cursor: response.pageInfo.nextCursor,\n items: [...cursorRequest.items, ...response.items],\n };\n }\n\n const response = await catalogApi.queryEntities({\n fullTextFilter: {\n term: initialRequest.text || '',\n fields: [\n 'metadata.name',\n 'kind',\n 'spec.profile.displayname',\n 'metadata.title',\n ],\n },\n filter: { kind: ['User', 'Group'] },\n orderFields: [{ field: 'metadata.name', order: 'asc' }],\n limit,\n });\n\n return {\n cursor: response.pageInfo.nextCursor,\n items: response.items,\n };\n },\n [],\n { loading: true },\n );\n}\n","/*\n * Copyright 2023 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 { useApi } from '@backstage/core-plugin-api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { catalogApiRef } from '../../api';\nimport { useState } from 'react';\nimport { Entity, parseEntityRef } from '@backstage/catalog-model';\n\ntype FacetsCursor = {\n start: number;\n text: string;\n};\n\ntype FacetsEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\ntype FacetsInitialRequest = {\n text: string;\n};\n\n/**\n * This hook asynchronously loads the entity owners using the facets endpoint.\n * EntityOwnerPicker uses this hook when mode=\"owners-only\" is passed as prop.\n * All the owners are kept internally in memory and rendered in batches once requested\n * by the frontend. The values returned by this hook are compatible with `useQueryEntities`\n * hook, which is also used by EntityOwnerPicker.\n * In this mode, the EntityOwnerPicker won't show detailed information of the owners.\n */\nexport function useFacetsEntities({ enabled }: { enabled: boolean }) {\n const catalogApi = useApi(catalogApiRef);\n\n const [facetsPromise] = useState(async () => {\n if (!enabled) {\n return [];\n }\n const facet = 'relations.ownedBy';\n\n return catalogApi\n .getEntityFacets({ facets: [facet] })\n .then(response =>\n response.facets[facet]\n .map(e => e.value)\n .map(ref => {\n const { kind, name, namespace } = parseEntityRef(ref);\n return {\n apiVersion: 'backstage.io/v1beta1',\n kind,\n metadata: { name, namespace },\n };\n })\n .sort(\n (a, b) =>\n a.kind.localeCompare(b.kind, 'en-US') ||\n a.metadata.namespace.localeCompare(\n b.metadata.namespace,\n 'en-US',\n ) ||\n a.metadata.name.localeCompare(b.metadata.name, 'en-US'),\n ),\n )\n .catch(() => []);\n });\n\n return useAsyncFn<\n (\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n options?: { limit?: number },\n ) => Promise<FacetsEntitiesResponse>\n >(\n async (request, options) => {\n const facets = await facetsPromise;\n\n if (!facets) {\n return {\n items: [],\n };\n }\n\n const limit = options?.limit ?? 20;\n\n const { text, start } = decodeCursor(request);\n const filteredRefs = facets.filter(e => filterEntity(text, e));\n const end = start + limit;\n return {\n items: filteredRefs.slice(0, end),\n ...encodeCursor({\n entities: filteredRefs,\n limit: end,\n payload: {\n text,\n start: end,\n },\n }),\n };\n },\n [facetsPromise],\n { loading: true, value: { items: [] } },\n );\n}\n\nfunction decodeCursor(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): FacetsCursor {\n if (isFacetsResponse(request) && request.cursor) {\n return JSON.parse(atob(request.cursor));\n }\n return {\n text: (request as FacetsInitialRequest).text || '',\n start: 0,\n };\n}\n\nfunction isFacetsResponse(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): request is FacetsEntitiesResponse {\n return !!(request as FacetsEntitiesResponse).cursor;\n}\n\nfunction encodeCursor({\n entities,\n limit,\n payload,\n}: {\n entities: Entity[];\n limit: number;\n payload: { text: string; start: number };\n}) {\n if (entities.length > limit) {\n return { cursor: btoa(JSON.stringify(payload)) };\n }\n return {};\n}\n\nfunction filterEntity(text: string, entity: Entity) {\n const normalizedText = text.trim();\n return (\n entity.kind.includes(normalizedText) ||\n entity.metadata.namespace?.includes(normalizedText) ||\n entity.metadata.name.includes(normalizedText)\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 { makeStyles } from '@material-ui/core/styles';\nimport { EntityTagFilter } from '../../filters';\nimport { EntityAutocompletePicker } from '../EntityAutocompletePicker/EntityAutocompletePicker';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityTagPickerClassKey = 'input';\n\n/** @public */\nexport type EntityTagPickerProps = {\n showCounts?: boolean;\n initialFilter?: string[];\n hidden?: boolean;\n};\n\nconst useStyles = makeStyles(\n { input: {} },\n { name: 'CatalogReactEntityTagPicker' },\n);\n\n/** @public */\nexport const EntityTagPicker = (props: EntityTagPickerProps) => {\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return (\n <EntityAutocompletePicker\n label={t('entityTagPicker.title')}\n name=\"tags\"\n path=\"metadata.tags\"\n Filter={EntityTagFilter}\n showCounts={props.showCounts}\n InputProps={{ className: classes.input }}\n initialSelectedOptions={props.initialFilter ? props.initialFilter : []}\n hidden={props.hidden}\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 {\n configApiRef,\n IconComponent,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Card from '@material-ui/core/Card';\nimport List from '@material-ui/core/List';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport { StarIcon } from '@backstage/core-components';\nimport { Fragment, useEffect, useMemo, useState } from 'react';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { UserListFilterKind } from '../../types';\nimport { useOwnedEntitiesCount } from './useOwnedEntitiesCount';\nimport { useAllEntitiesCount } from './useAllEntitiesCount';\nimport { useStarredEntitiesCount } from './useStarredEntitiesCount';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type CatalogReactUserListPickerClassKey =\n | 'root'\n | 'title'\n | 'listIcon'\n | 'menuItem'\n | 'groupWrapper';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: 'rgba(0, 0, 0, .11)',\n boxShadow: 'none',\n margin: theme.spacing(1, 0, 1, 0),\n },\n title: {\n margin: theme.spacing(1, 0, 0, 1),\n textTransform: 'uppercase',\n fontSize: 12,\n fontWeight: 'bold',\n },\n listIcon: {\n minWidth: 30,\n color: theme.palette.text.primary,\n },\n menuItem: {\n minHeight: theme.spacing(6),\n },\n groupWrapper: {\n margin: theme.spacing(1, 1, 2, 1),\n },\n }),\n { name: 'CatalogReactUserListPicker' },\n);\n\nexport type ButtonGroup = {\n name: string;\n items: {\n id: 'owned' | 'starred' | 'all';\n label: string;\n icon?: IconComponent;\n }[];\n};\n\nfunction getFilterGroups(\n orgName: string,\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n): ButtonGroup[] {\n return [\n {\n name: t('userListPicker.personalFilter.title'),\n items: [\n {\n id: 'owned',\n label: t('userListPicker.personalFilter.ownedLabel'),\n icon: SettingsIcon,\n },\n {\n id: 'starred',\n label: t('userListPicker.personalFilter.starredLabel'),\n icon: StarIcon,\n },\n ],\n },\n {\n name: orgName,\n items: [\n {\n id: 'all',\n label: t('userListPicker.orgFilterAllLabel'),\n },\n ],\n },\n ];\n}\n\n/** @public */\nexport type UserListPickerProps = {\n initialFilter?: UserListFilterKind;\n availableFilters?: UserListFilterKind[];\n hidden?: boolean;\n alwaysKeepFilters?: boolean;\n};\n\n/** @public */\nexport const UserListPicker = (props: UserListPickerProps) => {\n const { initialFilter, availableFilters, hidden, alwaysKeepFilters } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const orgName =\n configApi.getOptionalString('organization.name') ??\n t('userListPicker.defaultOrgName');\n const {\n filters,\n updateFilters,\n queryParameters: { user: userParameter },\n } = useEntityList();\n const kindParameter = filters.kind?.value?.toLowerCase();\n\n // Remove group items that aren't in availableFilters and exclude\n // any now-empty groups.\n const userAndGroupFilterIds = ['starred', 'all'];\n const filterGroups = getFilterGroups(orgName, t)\n .map(filterGroup => ({\n ...filterGroup,\n items: filterGroup.items.filter(({ id }) =>\n // TODO: avoid hardcoding kinds here\n ['group', 'user'].some(kind => kind === kindParameter)\n ? userAndGroupFilterIds.includes(id)\n : !availableFilters || availableFilters.includes(id),\n ),\n }))\n .filter(({ items }) => !!items.length);\n\n const {\n count: ownedEntitiesCount,\n loading: loadingOwnedEntities,\n filter: ownedEntitiesFilter,\n } = useOwnedEntitiesCount();\n const { count: allCount } = useAllEntitiesCount();\n const {\n count: starredEntitiesCount,\n filter: starredEntitiesFilter,\n loading: loadingStarredEntities,\n } = useStarredEntitiesCount();\n\n const queryParamUserFilter = useMemo(\n () => [userParameter].flat()[0],\n [userParameter],\n );\n\n const [selectedUserFilter, setSelectedUserFilter] = useState(\n (queryParamUserFilter as UserListFilterKind) ?? initialFilter,\n );\n\n const filterCounts = useMemo(() => {\n return {\n all: allCount,\n starred: starredEntitiesCount,\n owned: ownedEntitiesCount,\n };\n }, [starredEntitiesCount, ownedEntitiesCount, allCount]);\n\n // Set selected user filter on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamUserFilter) {\n setSelectedUserFilter(queryParamUserFilter as UserListFilterKind);\n }\n }, [queryParamUserFilter]);\n\n const loading = loadingOwnedEntities || loadingStarredEntities;\n\n useEffect(() => {\n if (\n !loading &&\n !!selectedUserFilter &&\n selectedUserFilter !== 'all' &&\n filterCounts[selectedUserFilter] === 0 &&\n !alwaysKeepFilters\n ) {\n setSelectedUserFilter('all');\n }\n }, [\n loading,\n filterCounts,\n selectedUserFilter,\n setSelectedUserFilter,\n alwaysKeepFilters,\n ]);\n\n useEffect(() => {\n if (!selectedUserFilter) {\n return;\n }\n if (loading) {\n return;\n }\n\n const getFilter = () => {\n if (selectedUserFilter === 'owned') {\n return ownedEntitiesFilter;\n }\n if (selectedUserFilter === 'starred') {\n return starredEntitiesFilter;\n }\n return EntityUserFilter.all();\n };\n\n updateFilters({ user: getFilter() });\n }, [\n selectedUserFilter,\n starredEntitiesFilter,\n ownedEntitiesFilter,\n updateFilters,\n\n loading,\n ]);\n\n return hidden ? null : (\n <Card className={classes.root}>\n {filterGroups.map(group => (\n <Fragment key={group.name}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.title}\n >\n {group.name}\n </Typography>\n <Card className={classes.groupWrapper}>\n <List disablePadding dense role=\"menu\" aria-label={group.name}>\n {group.items.map((item, index) => (\n <MenuItem\n role=\"none presentation\"\n key={item.id}\n divider={index !== group.items.length - 1}\n onClick={() => setSelectedUserFilter(item.id)}\n selected={item.id === filters.user?.value}\n className={classes.menuItem}\n disabled={filterCounts[item.id] === 0}\n data-testid={`user-picker-${item.id}`}\n tabIndex={0}\n ContainerProps={{ role: 'menuitem' }}\n >\n {item.icon && (\n <ListItemIcon className={classes.listIcon}>\n <item.icon fontSize=\"small\" />\n </ListItemIcon>\n )}\n <ListItemText>\n <Typography variant=\"body1\">{item.label} </Typography>\n </ListItemText>\n <ListItemSecondaryAction>\n {filterCounts[item.id] ?? '-'}\n </ListItemSecondaryAction>\n </MenuItem>\n ))}\n </List>\n </Card>\n </Fragment>\n ))}\n </Card>\n );\n};\n","/*\n * Copyright 2023 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 { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport { compact, intersection } from 'lodash';\nimport { useMemo } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityOwnerFilter, EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { CatalogFilters, reduceCatalogFilters } from '../../utils/filters';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDeepCompareEffect from 'react-use/esm/useDeepCompareEffect';\n\nexport function useOwnedEntitiesCount() {\n const identityApi = useApi(identityApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n const { filters } = useEntityList();\n\n const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync(\n async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs,\n // load only on mount\n [],\n );\n\n const { user, owners, ...allFilters } = filters;\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(\n compact(Object.values(allFilters)),\n );\n\n const [{ value: count, loading: loadingEntityOwnership }, fetchEntities] =\n useAsyncFn(\n async (req: {\n ownershipEntityRefs: string[];\n owners: EntityOwnerFilter | undefined;\n filter: CatalogFilters;\n }) => {\n const ownedClaims = getOwnedCountClaims(\n req.owners,\n req.ownershipEntityRefs,\n );\n if (ownedClaims === undefined) {\n // this implicitly means that there aren't claims in common with\n // the logged in users, so avoid invoking the queryEntities endpoint\n // which will implicitly returns 0\n return 0;\n }\n\n const { ['metadata.name']: metadata, ...filter } = req.filter.filter;\n\n const { totalItems } = await catalogApi.queryEntities({\n ...req.filter,\n filter: {\n ...filter,\n 'relations.ownedBy': ownedClaims,\n },\n limit: 0,\n });\n return totalItems;\n },\n [],\n { loading: true },\n );\n\n useDeepCompareEffect(() => {\n // context contains no filter, wait\n if (Object.keys(catalogFilters.filter).length === 0) {\n return;\n }\n // ownershipEntityRefs is loading, wait\n if (ownershipEntityRefs === undefined) {\n return;\n }\n fetchEntities({\n ownershipEntityRefs,\n owners,\n filter: catalogFilters,\n });\n }, [ownershipEntityRefs, owners, catalogFilters]);\n\n const loading = loadingEntityRefs || loadingEntityOwnership;\n\n return {\n count,\n loading,\n filter: useMemo(\n () => EntityUserFilter.owned(ownershipEntityRefs ?? []),\n [ownershipEntityRefs],\n ),\n ownershipEntityRefs,\n };\n}\n\nfunction getOwnedCountClaims(\n owners: EntityOwnerFilter | undefined,\n ownershipEntityRefs: string[] | undefined,\n) {\n if (ownershipEntityRefs === undefined) {\n return undefined;\n }\n const ownersRefs = owners?.values ?? [];\n if (ownersRefs.length) {\n const commonOwnedBy = intersection(ownersRefs, ownershipEntityRefs);\n if (commonOwnedBy.length === 0) {\n return undefined;\n }\n return commonOwnedBy;\n }\n return ownershipEntityRefs;\n}\n","/*\n * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { useEntityList } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useAllEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n limit: 0,\n };\n\n if (Object.keys(catalogFilters.filter).length === 0) {\n prevRequest.current = undefined;\n return prevRequest.current;\n }\n\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n return newRequest;\n }, [filters]);\n\n const { value: count, loading } = useAsync(async () => {\n if (request === undefined) {\n return 0;\n }\n const { totalItems } = await catalogApi.queryEntities(request);\n\n return totalItems;\n }, [request]);\n\n return { count, loading };\n}\n","/*\n * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList, useStarredEntities } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useStarredEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n const { starredEntities } = useStarredEntities();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n\n const facet = 'metadata.name';\n\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n filter: {\n ...catalogFilters.filter,\n /**\n * here we are filtering entities by `name`. Given this filter,\n * the response might contain more entities than expected, in case multiple entities\n * of different kind or namespace share the same name. Those extra entities are filtered out\n * client side by `EntityUserFilter`, so they won't be visible to the user.\n */\n [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name),\n },\n /**\n * limit is set to a high value as we are not expecting many starred entities\n */\n limit: 1000,\n };\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n\n return newRequest;\n }, [filters, starredEntities]);\n\n const { value: count, loading } = useAsync(async () => {\n if (!starredEntities.size) {\n return 0;\n }\n\n /**\n * given a list of starred entity refs and some filters coming from CatalogPage,\n * it reduces the list of starred entities, to a list of entities that matches the\n * provided filters. It won't be possible to getEntitiesByRefs\n * as the method doesn't accept any filter.\n */\n const response = await catalogApi.queryEntities(request);\n\n return response.items\n .map(e =>\n stringifyEntityRef({\n kind: e.kind,\n namespace: e.metadata.namespace,\n name: e.metadata.name,\n }),\n )\n .filter(e => starredEntities.has(e)).length;\n }, [request, starredEntities]);\n\n const filter = useMemo(\n () => EntityUserFilter.starred(Array.from(starredEntities)),\n [starredEntities],\n );\n\n return { count, loading, filter };\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 {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { AlphaEntity } from '@backstage/catalog-model/alpha';\nimport { EntityFilter, UserListFilterKind } from './types';\nimport { getEntityRelations } from './utils/getEntityRelations';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\n/**\n * Filter entities based on Kind.\n * @public\n */\nexport class EntityKindFilter implements EntityFilter {\n readonly value: string;\n readonly label: string;\n\n constructor(value: string, label: string) {\n this.value = value;\n this.label = label;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { kind: this.value };\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on type\n * @public\n */\nexport class EntityTypeFilter implements EntityFilter {\n readonly value: string | string[];\n\n constructor(value: string | string[]) {\n this.value = value;\n }\n\n // Simplify `string | string[]` for consumers, always returns an array\n getTypes(): string[] {\n return Array.isArray(this.value) ? this.value : [this.value];\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.type': this.getTypes() };\n }\n\n toQueryValue(): string[] {\n return this.getTypes();\n }\n}\n\n/**\n * Filters entities based on tag.\n * @public\n */\nexport class EntityTagFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.every(v => (entity.metadata.tags ?? []).includes(v));\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.tags': this.values };\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities where the text matches spec, title or tags.\n * @public\n */\nexport class EntityTextFilter implements EntityFilter {\n readonly value: string;\n\n constructor(value: string) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const words = this.toUpperArray(this.value.split(/\\s/));\n const exactMatch = this.toUpperArray([entity.metadata.tags]);\n const partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n (entity.spec?.profile as { displayName?: string })?.displayName,\n ]);\n\n for (const word of words) {\n if (\n exactMatch.every(m => m !== word) &&\n partialMatch.every(m => !m.includes(word))\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n getFullTextFilters() {\n return {\n term: this.value,\n // Update this to be more dynamic based on table columns.\n fields: ['metadata.name', 'metadata.title', 'spec.profile.displayName'],\n };\n }\n\n toQueryValue() {\n return this.value;\n }\n\n private toUpperArray(\n value: Array<string | string[] | undefined>,\n ): Array<string> {\n return value\n .flat()\n .filter((m): m is string => Boolean(m))\n .map(m => m.toLocaleUpperCase('en-US'));\n }\n}\n\n/**\n * Filter matching entities that are owned by group.\n * @public\n *\n * CAUTION: This class may contain both full and partial entity refs.\n */\nexport class EntityOwnerFilter implements EntityFilter {\n readonly values: string[];\n constructor(values: string[]) {\n this.values = values.reduce((fullRefs, ref) => {\n // Attempt to remove bad entity references here.\n try {\n fullRefs.push(\n stringifyEntityRef(parseEntityRef(ref, { defaultKind: 'Group' })),\n );\n return fullRefs;\n } catch (err) {\n return fullRefs;\n }\n }, [] as string[]);\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'relations.ownedBy': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v =>\n getEntityRelations(entity, RELATION_OWNED_BY).some(\n o => stringifyEntityRef(o) === v,\n ),\n );\n }\n\n /**\n * Get the URL query parameter value. May be a mix of full and humanized entity refs.\n * @returns list of entity refs.\n */\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities on lifecycle.\n * @public\n */\nexport class EntityLifecycleFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.lifecycle': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.spec?.lifecycle === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities to those within the given namespace(s).\n * @public\n */\nexport class EntityNamespaceFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.namespace': this.values };\n }\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.metadata.namespace === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * @public\n */\nexport class EntityUserFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly refs?: string[];\n\n private constructor(value: UserListFilterKind, refs?: string[]) {\n this.value = value;\n this.refs = refs;\n }\n\n static owned(ownershipEntityRefs: string[]) {\n return new EntityUserFilter('owned', ownershipEntityRefs);\n }\n\n static all() {\n return new EntityUserFilter('all');\n }\n\n static starred(starredEntityRefs: string[]) {\n return new EntityUserFilter('starred', starredEntityRefs);\n }\n\n getCatalogFilters(): Record<string, string[]> {\n if (this.value === 'owned') {\n return { 'relations.ownedBy': this.refs ?? [] };\n }\n if (this.value === 'starred') {\n return {\n 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [],\n };\n }\n return {};\n }\n\n filterEntity(entity: Entity) {\n if (this.value === 'starred') {\n return this.refs?.includes(stringifyEntityRef(entity)) ?? true;\n }\n // used only for retro-compatibility with non paginated data.\n // This is supposed to return always true for paginated\n // owned entities, since the filters are applied server side.\n if (this.value === 'owned') {\n const relations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n this.refs?.some(v =>\n relations.some(o => stringifyEntityRef(o) === v),\n ) ?? false\n );\n }\n return true;\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on whatever the user has starred or owns them.\n * @deprecated use EntityUserFilter\n * @public\n */\nexport class UserListFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly isOwnedEntity: (entity: Entity) => boolean;\n readonly isStarredEntity: (entity: Entity) => boolean;\n\n constructor(\n value: UserListFilterKind,\n isOwnedEntity: (entity: Entity) => boolean,\n isStarredEntity: (entity: Entity) => boolean,\n ) {\n this.value = value;\n this.isOwnedEntity = isOwnedEntity;\n this.isStarredEntity = isStarredEntity;\n }\n\n filterEntity(entity: Entity): boolean {\n switch (this.value) {\n case 'owned':\n return this.isOwnedEntity(entity);\n case 'starred':\n return this.isStarredEntity(entity);\n default:\n return true;\n }\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based if it is an orphan or not.\n * @public\n */\nexport class EntityOrphanFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n if (this.value) {\n return { 'metadata.annotations.backstage.io/orphan': String(this.value) };\n }\n return {};\n }\n\n filterEntity(entity: Entity): boolean {\n const orphan = entity.metadata.annotations?.['backstage.io/orphan'];\n return orphan !== undefined && this.value.toString() === orphan;\n }\n}\n\n/**\n * Filters entities based on if it has errors or not.\n * @public\n */\nexport class EntityErrorFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const error =\n ((entity as AlphaEntity)?.status?.items?.length as number) > 0;\n return error !== undefined && this.value === error;\n }\n}\n\n/**\n * Sort entities by a given field/column.\n * @public\n */\nexport class EntityOrderFilter implements EntityFilter {\n readonly values: [string, 'asc' | 'desc'][];\n\n constructor(values: [string, 'asc' | 'desc'][]) {\n this.values = values;\n }\n\n getOrderFilters(): EntityOrderQuery {\n return this.values.map(([field, order]) => ({ field, order }));\n }\n\n toQueryValue(): string[] {\n return this.values.flat();\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 { QueryEntitiesResponse } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n useVersionedContext,\n} from '@backstage/version-bridge';\nimport { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport useMountedState from 'react-use/esm/useMountedState';\nimport { catalogApiRef } from '../api';\nimport {\n EntityErrorFilter,\n EntityKindFilter,\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityFilter, EntityListPagination } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils/filters';\n\n/** @public */\nexport type DefaultEntityFilters = {\n kind?: EntityKindFilter;\n type?: EntityTypeFilter;\n user?: UserListFilter | EntityUserFilter;\n owners?: EntityOwnerFilter;\n lifecycles?: EntityLifecycleFilter;\n tags?: EntityTagFilter;\n text?: EntityTextFilter;\n orphan?: EntityOrphanFilter;\n error?: EntityErrorFilter;\n namespace?: EntityNamespaceFilter;\n order?: EntityOrderFilter;\n};\n\n/** @public */\nexport type PaginationMode = 'cursor' | 'offset' | 'none';\n\n/** @public */\nexport type EntityListContextProps<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n> = {\n /**\n * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension\n * of that default (to add custom filter types).\n */\n filters: EntityFilters;\n\n /**\n * The resolved list of catalog entities, after all filters are applied.\n */\n entities: Entity[];\n\n /**\n * The resolved list of catalog entities, after _only catalog-backend_ filters are applied.\n */\n backendEntities: Entity[];\n\n /**\n * Update one or more of the registered filters. Optional filters can be set to `undefined` to\n * reset the filter.\n */\n updateFilters: (\n filters:\n | Partial<EntityFilters>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => void;\n\n /**\n * Filter values from query parameters.\n */\n queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;\n\n loading: boolean;\n error?: Error;\n\n pageInfo?: {\n next?: () => void;\n prev?: () => void;\n };\n totalItems?: number;\n limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n};\n\n// This context has support for multiple concurrent versions of this package.\n// It is currently used in parallel with the old context in order to provide\n// a smooth transition, but will eventually be the only context we use.\nexport const NewEntityListContext = createVersionedContext<{\n 1: EntityListContextProps<any>;\n}>('entity-list-context');\n\n/**\n * Creates new context for entity listing and filtering.\n */\nexport const OldEntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype OutputState<EntityFilters extends DefaultEntityFilters> = {\n appliedFilters: EntityFilters;\n appliedCursor?: string;\n entities: Entity[];\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n offset?: number;\n limit?: number;\n};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: EntityListPagination;\n}>;\n\n/**\n * Provides entities and filters for a catalog listing.\n * @public\n */\nexport const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(\n props: EntityListProviderProps,\n) => {\n const isMounted = useMountedState();\n const catalogApi = useApi(catalogApiRef);\n const [requestedFilters, setRequestedFilters] = useState<EntityFilters>(\n {} as EntityFilters,\n );\n\n // We use react-router's useLocation hook so updates from external sources trigger an update to\n // the queryParameters in outputState. Updates from this hook use replaceState below and won't\n // trigger a useLocation change; this would instead come from an external source, such as a manual\n // update of the URL or two catalog sidebar links with different catalog filters.\n const location = useLocation();\n\n const getPaginationMode = (): PaginationMode => {\n if (props.pagination === true) {\n return 'cursor';\n }\n return typeof props.pagination === 'object'\n ? props.pagination.mode ?? 'cursor'\n : 'none';\n };\n\n const paginationMode = getPaginationMode();\n const paginationLimit =\n typeof props.pagination === 'object' ? props.pagination.limit ?? 20 : 20;\n\n const {\n queryParameters,\n cursor: initialCursor,\n offset: initialOffset,\n limit: initialLimit,\n } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n\n let limit = paginationLimit;\n if (typeof parsed.limit === 'string') {\n const queryLimit = Number.parseInt(parsed.limit, 10);\n if (!isNaN(queryLimit)) {\n limit = queryLimit;\n }\n }\n\n const offset =\n typeof parsed.offset === 'string' && paginationMode === 'offset'\n ? Number.parseInt(parsed.offset, 10)\n : undefined;\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor:\n typeof parsed.cursor === 'string' && paginationMode === 'cursor'\n ? parsed.cursor\n : undefined,\n offset:\n paginationMode === 'offset' && offset && !isNaN(offset)\n ? offset\n : undefined,\n limit,\n };\n }, [paginationMode, location.search, paginationLimit]);\n\n const [cursor, setCursor] = useState(initialCursor);\n const [offset, setOffset] = useState<number | undefined>(initialOffset);\n const [limit, setLimit] = useState(initialLimit);\n\n const [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: {},\n offset,\n limit,\n };\n },\n );\n\n // The main async filter worker. Note that while it has a lot of dependencies\n // in terms of its implementation, the triggering only happens (debounced)\n // based on the requested filters changing.\n const [{ value: resolvedValue, loading, error }, refresh] = useAsyncFn(\n async () => {\n const kindValue =\n requestedFilters.kind?.value?.toLocaleLowerCase('en-US');\n const adjustedFilters =\n kindValue === 'user' || kindValue === 'group'\n ? { ...requestedFilters, owners: undefined }\n : requestedFilters;\n const compacted = compact(Object.values(adjustedFilters));\n const entityFilter = reduceEntityFilters(compacted);\n\n if (paginationMode !== 'none') {\n if (cursor) {\n if (cursor !== outputState.appliedCursor) {\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n });\n return {\n appliedFilters: requestedFilters,\n appliedCursor: cursor,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n appliedCursor: outputState.appliedCursor,\n backendEntities: outputState.backendEntities,\n entities,\n pageInfo: outputState.pageInfo,\n totalItems: outputState.totalItems,\n limit: outputState.limit,\n offset: outputState.offset,\n };\n }\n\n const backendFilter = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n if (\n (paginationMode === 'offset' &&\n (outputState.limit !== limit || outputState.offset !== offset)) ||\n !isEqual(previousBackendFilter, backendFilter)\n ) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n });\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n limit,\n offset,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n pageInfo: outputState.pageInfo,\n totalItems: outputState.totalItems,\n limit: outputState.limit,\n offset: outputState.offset,\n };\n }\n\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const { orderFields } = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceBackendCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n // TODO(mtlewis): currently entities will never be requested unless\n // there's at least one filter, we should allow an initial request\n // to happen with no filters.\n if (!isEqual(previousBackendFilter, backendFilter)) {\n // TODO(timbonicus): should limit fields here, but would need filter\n // fields + table columns\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n order: orderFields,\n });\n const entities = response.items.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities,\n totalItems: entities.length,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n totalItems: entities.length,\n };\n },\n [\n catalogApi,\n queryParameters,\n requestedFilters,\n outputState,\n cursor,\n paginationMode,\n limit,\n offset,\n ],\n { loading: true },\n );\n\n // Slight debounce on the refresh, since (especially on page load) several\n // filters will be calling this in rapid succession.\n useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);\n\n useEffect(() => {\n if (resolvedValue === undefined) {\n return;\n }\n setOutputState(resolvedValue);\n if (isMounted()) {\n const queryParams = Object.keys(requestedFilters).reduce(\n (params, key) => {\n const filter = requestedFilters[key as keyof EntityFilters] as\n | EntityFilter\n | undefined;\n if (filter?.toQueryValue) {\n params[key] = filter.toQueryValue();\n }\n return params;\n },\n {} as Record<string, string | string[]>,\n );\n\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n const newParams = qs.stringify(\n {\n ...oldParams,\n filters: queryParams,\n ...(paginationMode === 'none' ? {} : { cursor, limit, offset }),\n },\n { addQueryPrefix: true, arrayFormat: 'repeat' },\n );\n const newUrl = `${window.location.pathname}${newParams}`;\n // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing, since we\n // don't want there to be back/forward slots for every single filter\n // change.\n window.history?.replaceState(null, document.title, newUrl);\n }\n }, [\n cursor,\n isMounted,\n limit,\n location.search,\n offset,\n requestedFilters,\n resolvedValue,\n paginationMode,\n ]);\n\n const updateFilters = useCallback(\n (\n update:\n | Partial<EntityFilter>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => {\n // changing filters will affect pagination, so we need to reset\n // the cursor and start from the first page.\n // TODO(vinzscam): this is currently causing issues at page reload\n // where the state is not kept. Unfortunately we need to rethink\n // the way filters work in order to fix this.\n if (paginationMode === 'cursor') {\n setCursor(undefined);\n } else if (paginationMode === 'offset') {\n // Same thing with offset\n setOffset(0);\n }\n setRequestedFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [paginationMode],\n );\n\n // Use resolvedValue directly when available to avoid an extra render cycle.\n // Without this, there's a render where loading has flipped back to false but\n // outputState hasn't been updated yet (it syncs via useEffect), causing a\n // flash of stale data between the loading state and the new results.\n const latestOutput = resolvedValue ?? outputState;\n\n const pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = latestOutput.pageInfo?.prevCursor;\n const nextCursor = latestOutput.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, latestOutput.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: latestOutput.appliedFilters,\n entities: latestOutput.entities,\n backendEntities: latestOutput.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems: latestOutput.totalItems,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n }),\n [\n latestOutput,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n limit,\n offset,\n paginationMode,\n setLimit,\n setOffset,\n ],\n );\n\n return (\n <OldEntityListContext.Provider value={value}>\n <NewEntityListContext.Provider\n value={createVersionedValueMap({ 1: value })}\n >\n {props.children}\n </NewEntityListContext.Provider>\n </OldEntityListContext.Provider>\n );\n};\n\n/**\n * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.\n * @public\n */\nexport function useEntityList<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n>(): EntityListContextProps<EntityFilters> {\n const versionedHolder = useVersionedContext<{\n 1: EntityListContextProps<any>;\n }>('entity-list-context');\n const oldContext = useContext(OldEntityListContext);\n\n if (versionedHolder) {\n const value = versionedHolder.atVersion(1);\n if (!value) {\n throw new Error('EntityListContext v1 not available');\n }\n return value;\n }\n\n if (oldContext) {\n return oldContext;\n }\n\n throw new Error('useEntityList must be used within EntityListProvider');\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 {\n Entity,\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useCallback, useMemo } from 'react';\nimport useObservable from 'react-use/esm/useObservable';\nimport { starredEntitiesApiRef } from '../apis';\n\nfunction getEntityRef(\n entityOrRef: Entity | CompoundEntityRef | string,\n): string {\n return typeof entityOrRef === 'string'\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n}\n\n/** @public */\nexport function useStarredEntities(): {\n starredEntities: Set<string>;\n toggleStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => void;\n isStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => boolean;\n} {\n const starredEntitiesApi = useApi(starredEntitiesApiRef);\n\n const starredEntities = useObservable(\n useMemo(() => starredEntitiesApi.starredEntitie$(), [starredEntitiesApi]),\n new Set<string>(),\n );\n\n const isStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntities.has(getEntityRef(entityOrRef)),\n [starredEntities],\n );\n\n const toggleStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(),\n [starredEntitiesApi],\n );\n\n return {\n starredEntities,\n toggleStarredEntity,\n isStarredEntity,\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 { Entity } from '@backstage/catalog-model';\nimport { EntityFilter } from '../types';\nimport {\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\nexport interface CatalogFilters {\n filter: Record<string, string | symbol | (string | symbol)[]>;\n fullTextFilter?: {\n term: string;\n };\n orderFields?: EntityOrderQuery;\n}\n\nfunction isEntityTextFilter(t: EntityFilter): t is EntityTextFilter {\n return !!(t as EntityTextFilter).getFullTextFilters;\n}\n\nfunction isEntityOrderFilter(t: EntityFilter): t is EntityOrderFilter {\n return !!(t as EntityOrderFilter).getOrderFilters;\n}\n\nexport function reduceCatalogFilters(filters: EntityFilter[]): CatalogFilters {\n const condensedFilters = filters.reduce<CatalogFilters['filter']>(\n (compoundFilter, filter) => {\n return {\n ...compoundFilter,\n ...(filter.getCatalogFilters ? filter.getCatalogFilters() : {}),\n };\n },\n {},\n );\n\n const fullTextFilter = filters.find(isEntityTextFilter)?.getFullTextFilters();\n\n const orderFields = filters.find(isEntityOrderFilter)?.getOrderFilters() || [\n {\n field: 'metadata.name',\n order: 'asc',\n },\n ];\n return { filter: condensedFilters, fullTextFilter, orderFields };\n}\n\n/**\n * This function computes and returns an object containing the filters to be sent\n * to the backend. Any filter coming from `EntityKindFilter` and `EntityTypeFilter`, together\n * with custom filter set by the adopters is allowed. This function is used by `EntityListProvider`\n * and it won't be needed anymore in the future once pagination is implemented, as all the filters\n * will be applied backend-side.\n */\nexport function reduceBackendCatalogFilters(filters: EntityFilter[]) {\n const backendCatalogFilters: Record<\n string,\n string | symbol | (string | symbol)[]\n > = {};\n\n filters.forEach(filter => {\n if (\n filter instanceof EntityTagFilter ||\n filter instanceof EntityOwnerFilter ||\n filter instanceof EntityLifecycleFilter ||\n filter instanceof EntityNamespaceFilter ||\n filter instanceof EntityUserFilter ||\n filter instanceof EntityOrphanFilter ||\n filter instanceof EntityTextFilter ||\n filter instanceof UserListFilter\n ) {\n return;\n }\n Object.assign(backendCatalogFilters, filter.getCatalogFilters?.() || {});\n });\n\n return backendCatalogFilters;\n}\n\nexport function reduceEntityFilters(\n filters: EntityFilter[],\n): (entity: Entity) => boolean {\n return (entity: Entity) =>\n filters.every(\n filter => !filter.filterEntity || filter.filterEntity(entity),\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 {\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsClient, TechDocsStorageClient } from './client';\nimport {\n rootDocsRouteRef,\n rootRouteRef,\n rootCatalogDocsRouteRef,\n} from './routes';\nimport {\n configApiRef,\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n createSearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '@backstage/plugin-search-react';\nimport { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem';\n\n/**\n * The Backstage plugin that renders technical documentation for your components\n *\n * @public\n */\nexport const techdocsPlugin = createPlugin({\n id: 'techdocs',\n apis: [\n createApiFactory({\n api: techdocsStorageApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsStorageClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n createApiFactory({\n api: techdocsApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n },\n});\n\n/**\n * Routable extension used to render docs\n *\n * @public\n */\nexport const TechdocsPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechdocsPage',\n component: () => import('./Router').then(m => m.Router),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Routable extension used to render docs on Entity page\n *\n * @public\n */\nexport const EntityTechdocsContent = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'EntityTechdocsContent',\n component: () => import('./Router').then(m => m.LegacyEmbeddedDocsRouter),\n mountPoint: rootCatalogDocsRouteRef,\n }),\n);\n\n/**\n * Component which takes a custom tabs config object and renders a documentation landing page.\n *\n * @public\n */\nexport const TechDocsCustomHome = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsCustomHome',\n component: () =>\n import('./home/components/TechDocsCustomHome').then(\n m => m.TechDocsCustomHome,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Responsible for rendering the provided router element\n *\n * @public\n */\nexport const TechDocsIndexPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsIndexPage',\n component: () =>\n import('./home/components/TechDocsIndexPage').then(\n m => m.TechDocsIndexPage,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Component responsible for composing a TechDocs reader page experience\n *\n * @public\n */\nexport const TechDocsReaderPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsReaderPage',\n component: () =>\n import('./reader/components/TechDocsReaderPage').then(\n m => m.TechDocsReaderPage,\n ),\n mountPoint: rootDocsRouteRef,\n }),\n);\n\n/**\n * React extension used to render results on Search page or modal\n *\n * @public\n */\nexport const TechDocsSearchResultListItem: (\n props: SearchResultListItemExtensionProps<TechDocsSearchResultListItemProps>,\n) => JSX.Element | null = techdocsPlugin.provide(\n createSearchResultListItemExtension({\n name: 'TechDocsSearchResultListItem',\n component: () =>\n import('./search/components/TechDocsSearchResultListItem').then(\n m => m.TechDocsSearchResultListItem,\n ),\n predicate: result => result.type === 'techdocs',\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 {\n PluginConfig,\n BackstagePlugin,\n Extension,\n AnyRoutes,\n AnyExternalRoutes,\n PluginFeatureFlagConfig,\n} from './types';\nimport { AnyApiFactory } from '../apis';\n\n/**\n * @internal\n */\nexport class PluginImpl<\n Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> implements BackstagePlugin<Routes, ExternalRoutes>\n{\n constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}\n\n getId(): string {\n return this.config.id;\n }\n\n getApis(): Iterable<AnyApiFactory> {\n return this.config.apis ?? [];\n }\n\n getFeatureFlags(): Iterable<PluginFeatureFlagConfig> {\n return this.config.featureFlags?.slice() ?? [];\n }\n\n get routes(): Routes {\n return this.config.routes ?? ({} as Routes);\n }\n\n get externalRoutes(): ExternalRoutes {\n return this.config.externalRoutes ?? ({} as ExternalRoutes);\n }\n\n provide<T>(extension: Extension<T>): T {\n return extension.expose(this);\n }\n\n toString() {\n return `plugin{${this.config.id}}`;\n }\n}\n\n/**\n * Creates Backstage Plugin from config.\n *\n * @param config - Plugin configuration.\n * @public\n */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n config: PluginConfig<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n return new PluginImpl(config);\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 {\n Entity,\n getCompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { getEntityRootTechDocsPath } from '@backstage/plugin-techdocs-react';\n\nimport { TechDocsReaderPage } from './plugin';\nimport { TechDocsReaderPageContent } from './reader/components/TechDocsReaderPageContent';\nimport { TechDocsReaderPageSubheader } from './reader/components/TechDocsReaderPageSubheader';\nimport { useEntityPageTechDocsRedirect } from './search/hooks/useTechDocsLocation';\n\ntype EntityPageDocsProps = {\n entity: Entity;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n};\n\nexport const EntityPageDocs = ({\n entity,\n withSearch = true,\n}: EntityPageDocsProps) => {\n let entityRef = getCompoundEntityRef(entity);\n\n const searchResultUrlMapper = useEntityPageTechDocsRedirect(entityRef);\n\n if (entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]) {\n try {\n entityRef = parseEntityRef(\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION],\n );\n } catch {\n // not a fan of this but we don't care if the parseEntityRef fails\n }\n }\n\n const defaultPath = getEntityRootTechDocsPath(entity);\n\n return (\n <TechDocsReaderPage entityRef={entityRef}>\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent\n withSearch={withSearch}\n searchResultUrlMapper={searchResultUrlMapper}\n defaultPath={defaultPath}\n />\n </TechDocsReaderPage>\n );\n};\n","/*\n * Copyright 2024 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 { useMemo } from 'react';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { rootCatalogDocsRouteRef, rootDocsRouteRef } from '../../routes';\n\nconst trimStartSlash = (path: string) => path.replace(/^\\/+/, '');\nconst trimEndSlash = (path: string) => path.replace(/\\/+$/, '');\n\n/**\n * Returns a function that takes a location to a Tech Docs entry, and returns a\n * new location, re-routed to the catalog page tab.\n *\n * @internal\n */\nexport function useEntityPageTechDocsRedirect(entityRef: CompoundEntityRef) {\n const { kind, name, namespace } = entityRef;\n\n const routeDocsRoot = useRouteRef(rootDocsRouteRef);\n const routeDocsCatalog = useRouteRef(rootCatalogDocsRouteRef);\n\n // Re-routes a /docs/:namespace/:kind/:name/* location into\n // /catalog/:namespace/:kind/:name/docs/*, while handling situations where\n // these defaults are changed.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const reRouteLocationToCatalog = useMemo(() => {\n const rootDocsPath = trimEndSlash(routeDocsRoot({ kind, namespace, name }));\n const catalogDocsPath = trimEndSlash(routeDocsCatalog());\n\n return (url: string): string => {\n if (\n url\n .toLocaleLowerCase('en-US')\n .startsWith(rootDocsPath.toLocaleLowerCase('en-US'))\n ) {\n const suffix = trimStartSlash(url.slice(rootDocsPath.length));\n return suffix.length === 0 || suffix.startsWith('#')\n ? `${catalogDocsPath}${suffix}`\n : `${catalogDocsPath}/${suffix}`;\n }\n return url;\n };\n }, [routeDocsRoot, routeDocsCatalog, kind, name, namespace]);\n\n return reRouteLocationToCatalog;\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 Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { CodeSnippet, Link, EmptyState } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { useEntity } from '../../hooks';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type MissingAnnotationEmptyStateClassKey = 'code';\n\nconst useStyles = makeStyles(\n theme => ({\n code: {\n borderRadius: 6,\n margin: theme.spacing(2, 0),\n background:\n theme.palette.type === 'dark' ? '#444' : theme.palette.common.white,\n },\n }),\n { name: 'BackstageMissingAnnotationEmptyState' },\n);\n\nfunction generateYamlExample(\n annotations: string[],\n entity?: Entity,\n): { yamlText: string; lineNumbers: number[] } {\n const kind = entity?.kind || 'Component';\n const name = entity?.metadata.name || 'example';\n const type = entity?.spec?.type || 'website';\n const owner = entity?.spec?.owner || 'user:default/guest';\n\n const yamlText = `apiVersion: backstage.io/v1alpha1\nkind: ${kind}\nmetadata:\n name: ${name}\n annotations:${annotations.map(ann => `\\n ${ann}: value`).join('')}\nspec:\n type: ${type}\n owner: ${owner}`;\n\n let line = 6; // Line 6 is the line number that annotations are added to.\n const lineNumbers: number[] = [];\n annotations.forEach(() => {\n lineNumbers.push(line);\n line++;\n });\n\n return {\n yamlText,\n lineNumbers,\n };\n}\n\nfunction generateDescription(\n annotations: string[],\n entityKind = 'Component',\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n) {\n const annotationList = annotations\n .map(ann => <code key={ann}>{ann}</code>)\n .reduce((prev, curr) => (\n <>\n {prev}, {curr}\n </>\n ));\n\n return t('missingAnnotationEmptyState.generateDescription', {\n count: annotations.length,\n entityKind,\n annotations: annotationList,\n });\n}\n\n/**\n * @public\n * Renders an empty state when an annotation is missing from an entity.\n */\nexport function MissingAnnotationEmptyState(props: {\n annotation: string | string[];\n readMoreUrl?: string;\n}) {\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n let entity: Entity | undefined;\n try {\n const entityContext = useEntity();\n entity = entityContext.entity;\n } catch (err) {\n // ignore when entity context doesnt exist\n }\n\n const { annotation, readMoreUrl } = props;\n const annotations = Array.isArray(annotation) ? annotation : [annotation];\n const url =\n readMoreUrl ||\n 'https://backstage.io/docs/features/software-catalog/well-known-annotations';\n const classes = useStyles();\n\n const entityKind = entity?.kind || 'Component';\n const { yamlText, lineNumbers } = generateYamlExample(annotations, entity);\n return (\n <EmptyState\n missing=\"field\"\n title={t('missingAnnotationEmptyState.title')}\n description={generateDescription(annotations, entityKind, t)}\n action={\n <>\n <Typography variant=\"body1\">\n {t('missingAnnotationEmptyState.annotationYaml', { entityKind })}\n </Typography>\n <Box className={classes.code}>\n <CodeSnippet\n text={yamlText}\n language=\"yaml\"\n showLineNumbers\n highlightedNumbers={lineNumbers}\n customStyle={{ background: 'inherit', fontSize: '115%' }}\n />\n </Box>\n <Button color=\"primary\" component={Link} to={url}>\n {t('missingAnnotationEmptyState.readMore')}\n </Button>\n </>\n }\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 */\n\nimport { ReactElement, PropsWithChildren } from 'react';\nimport { Route, Routes, useRoutes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { EntityPageDocs } from './EntityPageDocs';\nimport { TechDocsIndexPage } from './home/components/TechDocsIndexPage';\nimport { TechDocsReaderPage } from './reader/components/TechDocsReaderPage';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport {\n TECHDOCS_ANNOTATION,\n TECHDOCS_EXTERNAL_ANNOTATION,\n} from '@backstage/plugin-techdocs-common';\n\n/**\n * Helper that takes in entity and returns true/false if TechDocs is available for the entity\n *\n * @public\n */\nexport const isTechDocsAvailable = (entity: Entity) =>\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_ANNOTATION]) ||\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]);\n\n/**\n * Responsible for registering routes for TechDocs, TechDocs Homepage and separate TechDocs page\n *\n * @public\n */\nexport const Router = () => {\n return (\n <Routes>\n <Route path=\"/\" element={<TechDocsIndexPage />} />\n <Route\n path=\"/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n />\n </Routes>\n );\n};\n\nexport const TechDocsReaderRouter = (props: PropsWithChildren) => {\n const { children } = props;\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '*',\n element: <TechDocsReaderPage />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n return element;\n};\n\nexport const EmbeddedDocsRouter = (\n props: PropsWithChildren<{\n emptyState?: ReactElement;\n withSearch?: boolean;\n }>,\n) => {\n const { children, emptyState, withSearch = true } = props;\n const { entity } = useEntity();\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '/*',\n element: <EntityPageDocs entity={entity} withSearch={withSearch} />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n const projectId =\n entity.metadata.annotations?.[TECHDOCS_ANNOTATION] ||\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION];\n\n if (!projectId) {\n return (\n emptyState ?? (\n <MissingAnnotationEmptyState annotation={[TECHDOCS_ANNOTATION]} />\n )\n );\n }\n return element;\n};\n\n/**\n * Responsible for registering route to view docs on Entity page\n *\n * @public\n */\nexport const LegacyEmbeddedDocsRouter = ({\n children,\n withSearch = true,\n}: PropsWithChildren<{ withSearch?: boolean }>) => {\n // Wrap the Router to avoid exposing the emptyState prop in the non-alpha\n // public API and make it easier for us to change later.\n return <EmbeddedDocsRouter children={children} withSearch={withSearch} />;\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 { Config } from '@backstage/config';\n\n// Lower-case entity triplets by default, but allow override.\nexport function toLowerMaybe(str: string, config: Config) {\n return config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n )\n ? str\n : str.toLocaleLowerCase('en-US');\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 useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\n\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { Entity } from '@backstage/catalog-model';\nimport { rootDocsRouteRef } from '../../../routes';\nimport {\n EmptyState,\n LinkButton,\n Table,\n TableColumn,\n TableOptions,\n TableProps,\n} from '@backstage/core-components';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } from './types';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link DocsTable}.\n *\n * @public\n */\nexport type DocsTableProps = {\n entities: Entity[] | undefined;\n title?: string | undefined;\n loading?: boolean | undefined;\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table documents\n *\n * @public\n */\nexport const DocsTable = (props: DocsTableProps) => {\n const { entities, title, loading, columns, actions, options } = props;\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n if (!entities) return null;\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n const defaultActions: TableProps<DocsTableRow>['actions'] = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\n ];\n\n const pageSize = 20;\n const paging = documents && documents.length > pageSize;\n\n return (\n <>\n {loading || (documents && documents.length > 0) ? (\n <Table<DocsTableRow>\n isLoading={loading}\n options={{\n paging,\n pageSize,\n search: true,\n actionsColumnIndex: -1,\n ...options,\n }}\n data={documents}\n columns={columns || defaultColumns}\n actions={actions || defaultActions}\n title={\n title\n ? `${title} (${documents.length})`\n : `All (${documents.length})`\n }\n />\n ) : (\n <EmptyState\n missing=\"data\"\n title=\"No documents to show\"\n description=\"Create your own document. Check out our Getting Started Information\"\n action={\n <LinkButton\n color=\"primary\"\n to=\"https://backstage.io/docs/features/techdocs/getting-started\"\n variant=\"contained\"\n >\n DOCS\n </LinkButton>\n }\n />\n )}\n </>\n );\n};\n\nDocsTable.columns = columnFactories;\nDocsTable.actions = actionFactories;\n","/*\n * Copyright 2024 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 { useState, useEffect } from 'react';\n\nimport { Table, TableProps } from '@backstage/core-components';\nimport { DocsTableRow } from './types';\nimport {\n EntityTextFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\n\n/**\n * @internal\n */\nexport function OffsetPaginatedDocsTable(props: TableProps<DocsTableRow>) {\n const { actions, columns, data, isLoading, options, title } = props;\n const { updateFilters, setLimit, setOffset, limit, totalItems, offset } =\n useEntityList();\n const [page, setPage] = useState(\n offset && limit ? Math.floor(offset / limit) : 0,\n );\n\n useEffect(() => {\n if (totalItems && page * limit >= totalItems) {\n setOffset!(Math.max(0, totalItems - limit));\n } else {\n setOffset!(Math.max(0, page * limit));\n }\n }, [setOffset, page, limit, totalItems]);\n\n return (\n <Table<DocsTableRow>\n title={title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n pageSizeOptions: [5, 10, 20, 50, 100],\n pageSize: limit,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n ...options,\n }}\n actions={actions}\n onSearchChange={(searchText: string) =>\n updateFilters({\n text: searchText ? new EntityTextFilter(searchText) : undefined,\n })\n }\n page={page}\n onPageChange={newPage => {\n setPage(newPage);\n }}\n onRowsPerPageChange={pageSize => {\n setLimit(pageSize);\n }}\n totalCount={totalItems}\n localization={{ pagination: { labelDisplayedRows: '' } }}\n isLoading={isLoading}\n />\n );\n}\n","/*\n * Copyright 2024 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 { Table, TableProps } from '@backstage/core-components';\nimport { DocsTableRow } from './types';\n\ntype PaginatedDocsTableProps = {\n prev?(): void;\n next?(): void;\n} & TableProps<DocsTableRow>;\n\n/**\n * @internal\n */\n\nexport function CursorPaginatedDocsTable(props: PaginatedDocsTableProps) {\n const {\n actions,\n columns,\n data,\n next,\n prev,\n title,\n isLoading,\n options,\n ...restProps\n } = props;\n\n return (\n <Table\n title={isLoading ? '' : title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n ...options,\n // These settings are configured to force server side pagination\n pageSizeOptions: [],\n showFirstLastPageButtons: false,\n pageSize: Number.MAX_SAFE_INTEGER,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n }}\n onPageChange={page => {\n if (page > 0) {\n next?.();\n } else {\n prev?.();\n }\n }}\n /* this will enable the prev button accordingly */\n page={prev ? 1 : 0}\n /* this will enable the next button accordingly */\n totalCount={next ? Number.MAX_VALUE : Number.MAX_SAFE_INTEGER}\n localization={{ pagination: { labelDisplayedRows: '' } }}\n isLoading={isLoading}\n {...restProps}\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 useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\nimport { capitalize } from 'lodash';\nimport {\n CodeSnippet,\n TableColumn,\n TableOptions,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n useEntityList,\n useStarredEntities,\n} from '@backstage/plugin-catalog-react';\nimport { DocsTable } from './DocsTable';\nimport { OffsetPaginatedDocsTable } from './OffsetPaginatedDocsTable';\nimport { CursorPaginatedDocsTable } from './CursorPaginatedDocsTable';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } from './types';\nimport { rootDocsRouteRef } from '../../../routes';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link EntityListDocsTable}.\n *\n * @public\n */\nexport type EntityListDocsTableProps = {\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table with entities from catalog.\n *\n * @public\n */\nexport const EntityListDocsTable = (props: EntityListDocsTableProps) => {\n const { columns, actions, options } = props;\n const { loading, error, entities, filters, paginationMode, pageInfo } =\n useEntityList();\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n\n const title = capitalize(filters.user?.value ?? 'all');\n\n const defaultActions = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\n actionFactories.createStarEntityAction(\n isStarredEntity,\n toggleStarredEntity,\n ),\n ];\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n if (paginationMode === 'cursor') {\n return (\n <CursorPaginatedDocsTable\n columns={columns || defaultColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n next={pageInfo?.next}\n prev={pageInfo?.prev}\n />\n );\n } else if (paginationMode === 'offset') {\n return (\n <OffsetPaginatedDocsTable\n columns={columns || defaultColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n />\n );\n }\n\n if (error) {\n return (\n <WarningPanel\n severity=\"error\"\n title=\"Could not load available documentation.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n );\n }\n\n return (\n <DocsTable\n title={title}\n entities={entities}\n loading={loading}\n actions={actions || defaultActions}\n columns={columns}\n options={options}\n />\n );\n};\n\nEntityListDocsTable.columns = columnFactories;\nEntityListDocsTable.actions = actionFactories;\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 ShareIcon from '@material-ui/icons/Share';\nimport { DocsTableRow } from './types';\nimport { FavoriteToggleIcon } from '@backstage/core-components';\n\n/**\n * Not directly exported, but through DocsTable.actions and EntityListDocsTable.actions\n *\n * @public\n */\nexport const actionFactories = {\n createCopyDocsUrlAction(copyToClipboard: Function) {\n return (row: DocsTableRow) => {\n return {\n icon: () => <ShareIcon fontSize=\"small\" />,\n tooltip: 'Click to copy documentation link to clipboard',\n onClick: () =>\n copyToClipboard(`${window.location.origin}${row.resolved.docsUrl}`),\n };\n };\n },\n createStarEntityAction(\n isStarredEntity: Function,\n toggleStarredEntity: Function,\n ) {\n return (row: DocsTableRow) => {\n const entity = row.entity;\n const isStarred = isStarredEntity(entity);\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => <FavoriteToggleIcon isFavorite={isStarred} />,\n tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',\n onClick: () => toggleStarredEntity(entity),\n };\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 */\n\nimport Box from '@material-ui/core/Box';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ReactNode } from 'react';\n\nexport type SubvalueCellClassKey = 'value' | 'subvalue';\n\nconst useSubvalueCellStyles = makeStyles(\n theme => ({\n value: {\n marginBottom: theme.spacing(0.75),\n },\n subvalue: {\n color: theme.palette.textSubtle,\n fontWeight: 'normal',\n },\n }),\n { name: 'BackstageSubvalueCell' },\n);\n\ntype SubvalueCellProps = {\n value: ReactNode;\n subvalue: ReactNode;\n};\n\nexport function SubvalueCell(props: SubvalueCellProps) {\n const { value, subvalue } = props;\n const classes = useSubvalueCellStyles();\n\n return (\n <>\n <Box className={classes.value}>{value}</Box>\n <Box className={classes.subvalue}>{subvalue}</Box>\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 { Link, SubvalueCell, TableColumn } from '@backstage/core-components';\nimport { EntityRefLinks } from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(entity: Entity): string {\n return entity.metadata.title || entity.metadata.name;\n}\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: { hidden?: boolean }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn();\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n createNameColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Document',\n field: 'entity.metadata.name',\n highlight: true,\n searchable: true,\n defaultSort: 'asc',\n customSort: (row1, row2) => {\n const title1 = customTitle(row1.entity).toLocaleLowerCase();\n const title2 = customTitle(row2.entity).toLocaleLowerCase();\n return title1.localeCompare(title2);\n },\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>{customTitle(row.entity)}</Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Owner',\n field: 'resolved.ownedByRelationsTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.ownedByRelations}\n defaultKind=\"group\"\n />\n ),\n };\n },\n createKindColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Kind',\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n };\n },\n};\n\nexport const defaultColumns: TableColumn<DocsTableRow>[] = [\n columnFactories.createTitleColumn({ hidden: true }),\n columnFactories.createNameColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n];\n","/*\n * Copyright 2024 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 { RELATION_OWNED_BY, Entity } from '@backstage/catalog-model';\nimport {\n entityPresentationSnapshot,\n getEntityRelations,\n type EntityPresentationApi,\n} from '@backstage/plugin-catalog-react';\nimport { toLowerMaybe } from '../../../helpers';\nimport { ConfigApi, RouteFunc } from '@backstage/core-plugin-api';\n\ntype getRouteFunc = RouteFunc<{\n namespace: string;\n kind: string;\n name: string;\n}>;\n\nexport function entitiesToDocsMapper(\n entities: Entity[],\n getRouteToReaderPageFor: getRouteFunc,\n config: ConfigApi,\n entityPresentationApi?: EntityPresentationApi,\n) {\n return entities.map(entity => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return {\n entity,\n resolved: {\n docsUrl: getRouteToReaderPageFor({\n namespace: toLowerMaybe(\n entity.metadata.namespace ?? 'default',\n config,\n ),\n kind: toLowerMaybe(entity.kind, config),\n name: toLowerMaybe(entity.metadata.name, config),\n }),\n ownedByRelations,\n ownedByRelationsTitle: ownedByRelations\n .map(\n r =>\n entityPresentationSnapshot(\n r,\n { defaultKind: 'group' },\n entityPresentationApi,\n ).primaryTitle,\n )\n .join(', '),\n },\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 { ReactNode, FC } from 'react';\nimport {\n Content,\n ContentHeader,\n SupportButton,\n} from '@backstage/core-components';\nimport {\n CatalogFilterLayout,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport { TechDocsPageWrapper } from './TechDocsPageWrapper';\nimport { TechDocsPicker } from './TechDocsPicker';\nimport { EntityListDocsTable } from './Tables';\nimport { TechDocsIndexPageProps } from './TechDocsIndexPage';\n\n/**\n * Props for {@link DefaultTechDocsHome}\n *\n * @public\n * @deprecated Please use `TechDocsIndexPageProps` instead.\n */\nexport type DefaultTechDocsHomeProps = TechDocsIndexPageProps;\n\n/**\n * Component which renders a default documentation landing page.\n *\n * @public\n */\nexport const DefaultTechDocsHome = (props: TechDocsIndexPageProps) => {\n const {\n initialFilter = 'owned',\n columns,\n actions,\n ownerPickerMode,\n pagination,\n options,\n PageWrapper,\n CustomHeader,\n } = props;\n const Wrapper: FC<{\n children: ReactNode;\n }> = PageWrapper ? PageWrapper : TechDocsPageWrapper;\n const Header: FC =\n CustomHeader ||\n (() => (\n <ContentHeader title=\"\">\n <SupportButton>Discover documentation in your ecosystem.</SupportButton>\n </ContentHeader>\n ));\n return (\n <Wrapper>\n <Content>\n <Header />\n <EntityListProvider pagination={pagination}>\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <TechDocsPicker />\n <UserListPicker initialFilter={initialFilter} />\n <EntityOwnerPicker mode={ownerPickerMode} />\n <EntityTagPicker />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <EntityListDocsTable\n actions={actions}\n columns={columns}\n options={options}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n </EntityListProvider>\n </Content>\n </Wrapper>\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 { FC } from 'react';\nimport { useOutlet } from 'react-router-dom';\nimport {\n TableColumn,\n TableProps,\n TableOptions,\n} from '@backstage/core-components';\nimport {\n EntityListPagination,\n EntityOwnerPickerProps,\n UserListFilterKind,\n} from '@backstage/plugin-catalog-react';\nimport { DefaultTechDocsHome } from './DefaultTechDocsHome';\nimport { DocsTableRow } from './Tables';\n\n/**\n * Props for {@link TechDocsIndexPage}\n *\n * @public\n */\nexport type TechDocsIndexPageProps = {\n initialFilter?: UserListFilterKind;\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n ownerPickerMode?: EntityOwnerPickerProps['mode'];\n pagination?: EntityListPagination;\n options?: TableOptions<DocsTableRow>;\n PageWrapper?: FC;\n CustomHeader?: FC;\n};\n\nexport const TechDocsIndexPage = (props: TechDocsIndexPageProps) => {\n const outlet = useOutlet();\n\n return outlet || <DefaultTechDocsHome {...props} />;\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 { PropsWithChildren, ComponentProps } from 'react';\n\nimport { Header } from '../Header';\nimport { Page } from './Page';\n\ntype PageWithHeaderProps = ComponentProps<typeof Header> & {\n themeId: string;\n};\n\nexport function PageWithHeader(props: PropsWithChildren<PageWithHeaderProps>) {\n const { themeId, children, ...restProps } = props;\n return (\n <Page themeId={themeId}>\n <Header {...restProps} />\n {children}\n </Page>\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 { ReactNode, FC } from 'react';\n\nimport { PageWithHeader } from '@backstage/core-components';\nimport { useApi, configApiRef } from '@backstage/core-plugin-api';\n\n/**\n * Props for {@link TechDocsPageWrapper}\n *\n * @public\n */\nexport type TechDocsPageWrapperProps = {\n children?: ReactNode;\n CustomPageWrapper?: FC<{ children?: ReactNode }>;\n};\n\n/**\n * Component wrapping a TechDocs page with Page and Header components\n *\n * @public\n */\nexport const TechDocsPageWrapper = (props: TechDocsPageWrapperProps) => {\n const { children, CustomPageWrapper } = props;\n const configApi = useApi(configApiRef);\n const generatedSubtitle = `Documentation available in ${\n configApi.getOptionalString('organization.name') ?? 'Backstage'\n }`;\n\n return (\n <>\n {CustomPageWrapper ? (\n <CustomPageWrapper>{children}</CustomPageWrapper>\n ) : (\n <PageWithHeader\n title=\"Documentation\"\n subtitle={generatedSubtitle}\n themeId=\"documentation\"\n >\n {children}\n </PageWithHeader>\n )}\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 { useEffect } from 'react';\nimport {\n CATALOG_FILTER_EXISTS,\n DefaultEntityFilters,\n EntityFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\n\nclass TechDocsFilter implements EntityFilter {\n getCatalogFilters(): Record<string, string | symbol | (string | symbol)[]> {\n return {\n [`metadata.annotations.${TECHDOCS_ANNOTATION}`]: CATALOG_FILTER_EXISTS,\n };\n }\n}\n\ntype CustomFilters = DefaultEntityFilters & {\n techdocs?: TechDocsFilter;\n};\n\n/**\n * Component responsible for updating TechDocs filters\n *\n * @public\n */\nexport const TechDocsPicker = () => {\n const { updateFilters } = useEntityList<CustomFilters>();\n\n useEffect(() => {\n updateFilters({\n techdocs: new TechDocsFilter(),\n });\n }, [updateFilters]);\n\n return null;\n};\n","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutProperties from \"@babel/runtime/helpers/esm/objectWithoutProperties\";\nimport * as React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { alpha, withStyles } from '@material-ui/core/styles';\nexport var styles = function styles(theme) {\n return {\n /* Styles applied to the root element. */\n root: {\n display: 'block',\n // Create a \"on paper\" color with sufficient contrast retaining the color\n backgroundColor: alpha(theme.palette.text.primary, theme.palette.type === 'light' ? 0.11 : 0.13),\n height: '1.2em'\n },\n\n /* Styles applied to the root element if `variant=\"text\"`. */\n text: {\n marginTop: 0,\n marginBottom: 0,\n height: 'auto',\n transformOrigin: '0 60%',\n transform: 'scale(1, 0.60)',\n borderRadius: theme.shape.borderRadius,\n '&:empty:before': {\n content: '\"\\\\00a0\"'\n }\n },\n\n /* Styles applied to the root element if `variant=\"rect\"`. */\n rect: {},\n\n /* Styles applied to the root element if `variant=\"circle\"`. */\n circle: {\n borderRadius: '50%'\n },\n\n /* Styles applied to the root element if `animation=\"pulse\"`. */\n pulse: {\n animation: '$pulse 1.5s ease-in-out 0.5s infinite'\n },\n '@keyframes pulse': {\n '0%': {\n opacity: 1\n },\n '50%': {\n opacity: 0.4\n },\n '100%': {\n opacity: 1\n }\n },\n\n /* Styles applied to the root element if `animation=\"wave\"`. */\n wave: {\n position: 'relative',\n overflow: 'hidden',\n '&::after': {\n animation: '$wave 1.6s linear 0.5s infinite',\n background: \"linear-gradient(90deg, transparent, \".concat(theme.palette.action.hover, \", transparent)\"),\n content: '\"\"',\n position: 'absolute',\n transform: 'translateX(-100%)',\n // Avoid flash during server-side hydration\n bottom: 0,\n left: 0,\n right: 0,\n top: 0\n }\n },\n '@keyframes wave': {\n '0%': {\n transform: 'translateX(-100%)'\n },\n '60%': {\n // +0.5s of delay between each loop\n transform: 'translateX(100%)'\n },\n '100%': {\n transform: 'translateX(100%)'\n }\n },\n\n /* Styles applied when the component is passed children. */\n withChildren: {\n '& > *': {\n visibility: 'hidden'\n }\n },\n\n /* Styles applied when the component is passed children and no width. */\n fitContent: {\n maxWidth: 'fit-content'\n },\n\n /* Styles applied when the component is passed children and no height. */\n heightAuto: {\n height: 'auto'\n }\n };\n};\nvar Skeleton = /*#__PURE__*/React.forwardRef(function Skeleton(props, ref) {\n var _props$animation = props.animation,\n animation = _props$animation === void 0 ? 'pulse' : _props$animation,\n classes = props.classes,\n className = props.className,\n _props$component = props.component,\n Component = _props$component === void 0 ? 'span' : _props$component,\n height = props.height,\n _props$variant = props.variant,\n variant = _props$variant === void 0 ? 'text' : _props$variant,\n width = props.width,\n other = _objectWithoutProperties(props, [\"animation\", \"classes\", \"className\", \"component\", \"height\", \"variant\", \"width\"]);\n\n var hasChildren = Boolean(other.children);\n return /*#__PURE__*/React.createElement(Component, _extends({\n ref: ref,\n className: clsx(classes.root, classes[variant], className, hasChildren && [classes.withChildren, !width && classes.fitContent, !height && classes.heightAuto], animation !== false && classes[animation])\n }, other, {\n style: _extends({\n width: width,\n height: height\n }, other.style)\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? Skeleton.propTypes = {\n /**\n * The animation.\n * If `false` the animation effect is disabled.\n */\n animation: PropTypes.oneOf(['pulse', 'wave', false]),\n\n /**\n * Optional children to infer width and height from.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n * See [CSS API](#css) below for more details.\n */\n classes: PropTypes.object.isRequired,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes\n /* @typescript-to-proptypes-ignore */\n .elementType,\n\n /**\n * Height of the skeleton.\n * Useful when you don't want to adapt the skeleton to a text element but for instance a card.\n */\n height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n\n /**\n * The type of content that will be rendered.\n */\n variant: PropTypes.oneOf(['text', 'rect', 'circle']),\n\n /**\n * Width of the skeleton.\n * Useful when the skeleton is inside an inline element with no width of its own.\n */\n width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])\n} : void 0;\nexport default withStyles(styles, {\n name: 'MuiSkeleton'\n})(Skeleton);","/*\n * Copyright 2022 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 { PropsWithChildren } from 'react';\nimport Helmet from 'react-helmet';\n\nimport Grid from '@material-ui/core/Grid';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport CodeIcon from '@material-ui/icons/Code';\n\nimport {\n TechDocsAddonLocations as locations,\n TechDocsEntityMetadata,\n TechDocsMetadata,\n} from '@backstage/plugin-techdocs-react';\nimport {\n EntityRefLink,\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { RELATION_OWNED_BY, CompoundEntityRef } from '@backstage/catalog-model';\nimport { Header, HeaderLabel } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport capitalize from 'lodash/capitalize';\n\nimport { rootRouteRef } from '../../../routes';\nimport { useTechDocsReaderHeaderData } from '../../../hooks/useTechDocsReaderHeaderData';\n\nconst skeleton = <Skeleton animation=\"wave\" variant=\"text\" height={40} />;\n\n/**\n * Props for {@link TechDocsReaderPageHeader}\n *\n * @public\n * @deprecated No need to pass down properties anymore. The component consumes data from `TechDocsReaderPageContext` instead. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom header.\n */\nexport type TechDocsReaderPageHeaderProps = PropsWithChildren<{\n entityRef?: CompoundEntityRef;\n entityMetadata?: TechDocsEntityMetadata;\n techDocsMetadata?: TechDocsMetadata;\n}>;\n\n/**\n * Renders the reader page header.\n * This component does not accept props, please use\n * the Tech Docs add-ons to customize it\n * @public\n */\nexport const TechDocsReaderPageHeader = (\n props: TechDocsReaderPageHeaderProps,\n) => {\n const { children } = props;\n const {\n title,\n subtitle,\n entityRef,\n entityMetadata,\n tabTitle,\n hidden,\n showSourceLink,\n sourceLink,\n addons,\n } = useTechDocsReaderHeaderData();\n\n const docsRootLink = useRouteRef(rootRouteRef)();\n\n if (hidden) return null;\n\n const { spec } = entityMetadata || {};\n const lifecycle = spec?.lifecycle;\n\n const ownedByRelations = entityMetadata\n ? getEntityRelations(entityMetadata, RELATION_OWNED_BY)\n : [];\n\n const labels = (\n <>\n <HeaderLabel\n label={capitalize(entityMetadata?.kind || 'entity')}\n value={\n <EntityRefLink\n color=\"inherit\"\n entityRef={entityRef}\n title={entityMetadata?.metadata.title}\n defaultKind=\"Component\"\n />\n }\n />\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n color=\"inherit\"\n entityRefs={ownedByRelations}\n defaultKind=\"group\"\n />\n }\n />\n )}\n {lifecycle ? (\n <HeaderLabel label=\"Lifecycle\" value={String(lifecycle)} />\n ) : null}\n {showSourceLink ? (\n <HeaderLabel\n label=\"\"\n value={\n <Grid container direction=\"column\" alignItems=\"center\">\n <Grid style={{ padding: 0 }} item>\n <CodeIcon style={{ marginTop: '-25px' }} />\n </Grid>\n <Grid style={{ padding: 0 }} item>\n Source\n </Grid>\n </Grid>\n }\n url={sourceLink}\n />\n ) : null}\n </>\n );\n\n return (\n <Header\n type=\"Documentation\"\n typeLink={docsRootLink}\n title={title || skeleton}\n subtitle={subtitle === '' ? undefined : subtitle || skeleton}\n >\n <Helmet titleTemplate=\"%s\">\n <title>{tabTitle}</title>\n </Helmet>\n {labels}\n {children}\n {addons.renderComponentsByLocation(locations.Header)}\n </Header>\n );\n};\n","/*\n * Copyright 2024 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 { ReactNode } from 'react';\nimport { ErrorPanel } from '@backstage/core-components';\nimport { useApp } from '@backstage/core-plugin-api';\nimport Button from '@material-ui/core/Button';\nimport { useCookieAuthRefresh } from '../../hooks';\n\n/**\n * @public\n * Props for the {@link CookieAuthRefreshProvider} component.\n */\nexport type CookieAuthRefreshProviderProps = {\n // The plugin ID used for discovering the API origin\n pluginId: string;\n // The children to render when the refresh is successful\n children: ReactNode;\n};\n\n/**\n * @public\n * A provider that will refresh the cookie when it is about to expire.\n */\nexport function CookieAuthRefreshProvider(\n props: CookieAuthRefreshProviderProps,\n): JSX.Element {\n const { children, ...options } = props;\n const app = useApp();\n const { Progress } = app.getComponents();\n\n const result = useCookieAuthRefresh(options);\n\n if (result.status === 'loading') {\n return <Progress />;\n }\n\n if (result.status === 'error') {\n return (\n <ErrorPanel error={result.error}>\n <Button variant=\"outlined\" onClick={result.retry}>\n Retry\n </Button>\n </ErrorPanel>\n );\n }\n\n return <>{children}</>;\n}\n","/*\n * Copyright 2024 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 { useEffect, useCallback, useMemo } from 'react';\nimport {\n discoveryApiRef,\n fetchApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { useAsync, useMountEffect } from '@react-hookz/web';\nimport { ResponseError } from '@backstage/errors';\n\nconst COOKIE_PATH = '/.backstage/auth/v1/cookie';\nconst ONE_YEAR_MS = 365 * 24 * 3600_000;\n\n/**\n * @public\n * A hook that will refresh the cookie when it is about to expire.\n * @param options - Options for configuring the refresh cookie endpoint\n */\nexport function useCookieAuthRefresh(options: {\n // The plugin id used for discovering the API origin\n pluginId: string;\n}):\n | { status: 'loading' }\n | { status: 'error'; error: Error; retry: () => void }\n | { status: 'success'; data: { expiresAt: string } } {\n const { pluginId } = options ?? {};\n const fetchApi = useApi(fetchApiRef);\n const discoveryApi = useApi(discoveryApiRef);\n\n const channel = useMemo(() => {\n return 'BroadcastChannel' in window\n ? new BroadcastChannel(`${pluginId}-auth-cookie-expires-at`)\n : null;\n }, [pluginId]);\n\n const [state, actions] = useAsync<{ expiresAt: string }>(async () => {\n const apiOrigin = await discoveryApi.getBaseUrl(pluginId);\n const requestUrl = `${apiOrigin}${COOKIE_PATH}`;\n const response = await fetchApi.fetch(`${requestUrl}`, {\n credentials: 'include',\n });\n if (!response.ok) {\n // If we get a 404 from the cookie endpoint we assume that it does not\n // exist and cookie auth is not needed. For all active tabs we don't\n // schedule another refresh for the foreseeable future, but new tabs will\n // still check if cookie auth has been added to the deployment.\n // TODO(Rugvip): Once the legacy backend system is no longer supported we should remove this check\n if (response.status === 404) {\n return { expiresAt: new Date(Date.now() + ONE_YEAR_MS) };\n }\n throw await ResponseError.fromResponse(response);\n }\n const data = await response.json();\n if (!data.expiresAt) {\n throw new Error('No expiration date found in response');\n }\n return data;\n });\n\n useMountEffect(actions.execute);\n\n const retry = useCallback(() => {\n actions.execute();\n }, [actions]);\n\n const refresh = useCallback(\n (params: { expiresAt: string }) => {\n // Randomize the refreshing margin with a margin of 1-4 minutes to avoid all tabs refreshing at the same time\n // It cannot be less than 5 minutes otherwise the backend will return the same expiration date\n const margin = (1 + 3 * Math.random()) * 60000;\n const delay = Date.parse(params.expiresAt) - Date.now() - margin;\n const timeout = setTimeout(retry, delay);\n return () => clearTimeout(timeout);\n },\n [retry],\n );\n\n useEffect(() => {\n // Only schedule a refresh if we have a successful response\n if (state.status !== 'success' || !state.result) {\n return () => {};\n }\n channel?.postMessage({\n action: 'COOKIE_REFRESH_SUCCESS',\n payload: state.result,\n });\n let cancel = refresh(state.result);\n const listener = (\n event: MessageEvent<{ action: string; payload: { expiresAt: string } }>,\n ) => {\n const { action, payload } = event.data;\n if (action === 'COOKIE_REFRESH_SUCCESS') {\n cancel();\n cancel = refresh(payload);\n }\n };\n channel?.addEventListener('message', listener);\n return () => {\n cancel();\n channel?.removeEventListener('message', listener);\n };\n }, [state, refresh, channel]);\n\n // Initialising\n if (state.status === 'not-executed') {\n return { status: 'loading' };\n }\n\n // First refresh or retrying without any success before\n // Possible state transitions:\n // e.g. not-executed -> loading (first-refresh)\n // e.g. not-executed -> loading (first-refresh) -> error -> loading (manual-retry)\n if (state.status === 'loading' && !state.result) {\n return { status: 'loading' };\n }\n\n // Retrying after having succeeding at least once\n // Current state is: { status: 'loading', result: {...}, error: undefined | Error }\n // e.g. not-executed -> loading (first-refresh) -> success -> loading (scheduled-refresh) -> error -> loading (manual-retry)\n if (state.status === 'loading' && state.error) {\n return { status: 'loading' };\n }\n\n // Something went wrong during any situation of a refresh\n if (state.status === 'error' && state.error) {\n return { status: 'error', error: state.error, retry };\n }\n\n // At this point it should be safe to assume that we have a successful refresh\n return { status: 'success', data: state.result! };\n}\n","import { useMemo, useRef, useState } from 'react';\nimport { useSyncedRef } from '../useSyncedRef/index.js';\nexport function useAsync(asyncFn, initialValue) {\n const [state, setState] = useState({\n status: 'not-executed',\n error: undefined,\n result: initialValue,\n });\n const promiseRef = useRef();\n const argsRef = useRef();\n const methods = useSyncedRef({\n execute(...params) {\n argsRef.current = params;\n const promise = asyncFn(...params);\n promiseRef.current = promise;\n setState((s) => ({ ...s, status: 'loading' }));\n promise.then((result) => {\n if (promise === promiseRef.current) {\n setState((s) => ({ ...s, status: 'success', error: undefined, result }));\n }\n }, (error) => {\n if (promise === promiseRef.current) {\n setState((s) => ({ ...s, status: 'error', error }));\n }\n });\n return promise;\n },\n reset() {\n setState({\n status: 'not-executed',\n error: undefined,\n result: initialValue,\n });\n promiseRef.current = undefined;\n argsRef.current = undefined;\n },\n });\n return [\n state,\n useMemo(() => ({\n reset() {\n methods.current.reset();\n },\n execute: (...params) => methods.current.execute(...params),\n }), []),\n { promise: promiseRef.current, lastArgs: argsRef.current },\n ];\n}\n","/*\n * Copyright 2022 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 { Children, ReactElement, ReactNode, useMemo } from 'react';\nimport { useOutlet } from 'react-router-dom';\nimport { Page, Progress } from '@backstage/core-components';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport {\n TECHDOCS_ADDONS_KEY,\n TECHDOCS_ADDONS_WRAPPER_KEY,\n TechDocsReaderPageProvider,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsReaderPageRenderFunction } from '../../../types';\nimport { TechDocsReaderPageContent } from '../TechDocsReaderPageContent';\nimport { TechDocsReaderPageHeader } from '../TechDocsReaderPageHeader';\nimport { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader';\nimport { rootDocsRouteRef } from '../../../routes';\nimport {\n getComponentData,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { CookieAuthRefreshProvider } from '@backstage/plugin-auth-react';\nimport {\n createTheme,\n styled,\n ThemeOptions,\n ThemeProvider,\n useTheme,\n} from '@material-ui/core/styles';\nimport { useExternalRedirect } from './useExternalRedirect';\n\n/* An explanation for the multiple ways of customizing the TechDocs reader page\n\nPlease refer to this page on the microsite for the latest recommended approach:\nhttps://backstage.io/docs/features/techdocs/how-to-guides#how-to-customize-the-techdocs-reader-page\n\nThe <TechDocsReaderPage> component is responsible for rendering the <TechDocsReaderPageProvider> and\nits contained version of a <Page>, which in turn renders the <TechDocsReaderPageContent>.\n\nHistorically, there have been different approaches on how this <Page> can be customized, and how the\n<TechDocsReaderPageContent> inside could be exchanged for a custom implementation (which was not\npossible before). Also, the current implementation supports every scenario to avoid breaking default\nconfigurations of TechDocs.\n\nIn particular, there are 4 different TechDocs page configurations:\n\nCONFIGURATION 1: <TechDocsReaderPage> only, no children\n\n<Route path=\"/docs/:namespace/:kind/:name/*\" element={<TechDocsReaderPage />} >\n\nThis is the simplest way to use TechDocs. Only a full page is passed, assuming that it comes with\nits content inside. Since we allowed customizing it, we started providing <TechDocsReaderLayout> as\na default implementation (which contains <TechDocsReaderPageContent>).\n\nCONFIGURATION 2 (not advised): <TechDocsReaderPage> with element children\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={\n <TechDocsReaderPage>\n {techdocsPage}\n </TechDocsReaderPage>\n }\n/>\n\nPreviously, there were two ways of passing children to <TechDocsReaderPage>: either as elements (as\nshown above), or as a render function (described below in CONFIGURATION 3). The \"techdocsPage\" is\nlocated in packages/app/src/components/techdocs and is the default implementation of the content\ninside.\n\nCONFIGURATION 3 (not advised): <TechDocsReaderPage> with render function as child\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={\n <TechDocsReaderPage>\n {({ metadata, entityMetadata, onReady }) => (\n techdocsPage\n )}\n </TechDocsReaderPage>\n }\n/>\n\nSimilar to CONFIGURATION 2, the direct children will be passed to the <TechDocsReaderPage> but in\nthis case interpreted as render prop.\n\nCONFIGURATION 4: <TechDocsReaderPage> and provided content in <Route>\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n>\n {techDocsPage}\n <TechDocsAddons>\n <ExpandableNavigation />\n <ReportIssue />\n <TextSize />\n <LightBox />\n </TechDocsAddons>\n</Route>\n\nThis is the current state in packages/app/src/App.tsx and moved the location of children from inside\nthe element prop in the <Route> to the children of the <Route>. Then, in <TechDocsReaderPage> they\nare retrieved using the useOutlet hook from React Router.\n\nNOTE: Render functions are no longer supported in this approach.\n*/\n\n/**\n * Props for {@link TechDocsReaderLayout}\n * @public\n */\nexport type TechDocsReaderLayoutProps = {\n /**\n * Show or hide the header, defaults to true.\n */\n withHeader?: boolean;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n};\n\n/**\n * Default TechDocs reader page structure composed with a header and content\n * @public\n */\nexport const TechDocsReaderLayout = (props: TechDocsReaderLayoutProps) => {\n const { withSearch, withHeader = true } = props;\n return (\n <Page themeId=\"documentation\">\n {withHeader && <TechDocsReaderPageHeader />}\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent withSearch={withSearch} />\n </Page>\n );\n};\n\n/**\n * @public\n */\nexport type TechDocsReaderPageProps = {\n entityRef?: CompoundEntityRef;\n children?: TechDocsReaderPageRenderFunction | ReactNode;\n overrideThemeOptions?: Partial<ThemeOptions>;\n};\n\n/**\n * Styled Backstage Page that fills available vertical space\n */\nconst StyledPage = styled(Page)({\n height: 'inherit',\n overflowY: 'visible',\n});\n\n/**\n * An addon-aware implementation of the TechDocsReaderPage.\n *\n * @public\n */\nexport const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {\n const currentTheme = useTheme();\n\n const readerPageTheme = useMemo(\n () =>\n createTheme({\n ...currentTheme,\n ...(props.overrideThemeOptions || {}),\n }),\n [currentTheme, props.overrideThemeOptions],\n );\n\n const { kind, name, namespace } = useRouteRefParams(rootDocsRouteRef);\n const { children, entityRef = { kind, name, namespace } } = props;\n\n const outlet = useOutlet();\n\n const memoizedEntityRef = useMemo(\n () => ({\n kind: entityRef.kind,\n name: entityRef.name,\n namespace: entityRef.namespace,\n }),\n [entityRef.kind, entityRef.name, entityRef.namespace],\n );\n\n // Check for external TechDocs redirects and handle navigation\n const { shouldShowProgress } = useExternalRedirect(memoizedEntityRef);\n\n const page: ReactNode = useMemo(() => {\n if (children) {\n return null;\n }\n\n const childrenList = outlet ? Children.toArray(outlet.props.children) : [];\n\n const grandChildren = childrenList.flatMap<ReactElement>(\n child => (child as ReactElement)?.props?.children ?? [],\n );\n\n return grandChildren.find(\n grandChild =>\n !getComponentData(grandChild, TECHDOCS_ADDONS_WRAPPER_KEY) &&\n !getComponentData(grandChild, TECHDOCS_ADDONS_KEY),\n );\n }, [children, outlet]);\n\n // Show full-page loading spinner when checking for external redirects or about to redirect.\n // This replaces the entire page content (header, sidebar, and documentation).\n if (shouldShowProgress) {\n return <Progress />;\n }\n\n // As explained above, \"page\" is configuration 4 and <TechDocsReaderLayout> is 1\n if (!children) {\n return (\n <ThemeProvider theme={readerPageTheme}>\n <CookieAuthRefreshProvider pluginId=\"techdocs\">\n <TechDocsReaderPageProvider entityRef={memoizedEntityRef}>\n {(page as JSX.Element) || <TechDocsReaderLayout />}\n </TechDocsReaderPageProvider>\n </CookieAuthRefreshProvider>\n </ThemeProvider>\n );\n }\n\n // As explained above, a render function is configuration 3 and React element is 2\n return (\n <ThemeProvider theme={readerPageTheme}>\n <CookieAuthRefreshProvider pluginId=\"techdocs\">\n <TechDocsReaderPageProvider entityRef={memoizedEntityRef}>\n {({ metadata, entityMetadata, onReady }) => (\n <StyledPage\n themeId=\"documentation\"\n className=\"techdocs-reader-page\"\n >\n {children instanceof Function\n ? children({\n entityRef: memoizedEntityRef,\n techdocsMetadataValue: metadata.value,\n entityMetadataValue: entityMetadata.value,\n onReady,\n })\n : children}\n </StyledPage>\n )}\n </TechDocsReaderPageProvider>\n </CookieAuthRefreshProvider>\n </ThemeProvider>\n );\n};\n","/*\n * Copyright 2025 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 { useEffect, useRef } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport {\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { buildTechDocsURL } from '@backstage/plugin-techdocs-react';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { rootDocsRouteRef } from '../../../routes';\n\n/**\n * Hook to handle external TechDocs redirects based on entity annotations.\n * Checks if an entity has the `backstage.io/techdocs-entity` annotation and\n * redirects to the external TechDocs URL if present.\n *\n * @param entityRef - The entity reference to check for external redirects\n * @returns Object containing loading state and whether a redirect is in progress\n *\n * @internal\n */\nexport function useExternalRedirect(entityRef: CompoundEntityRef): {\n loading: boolean;\n shouldShowProgress: boolean;\n} {\n const catalogApi = useApi(catalogApiRef);\n const navigate = useNavigate();\n const viewTechdocLink = useRouteRef(rootDocsRouteRef);\n\n // Create a stable string key for the entity to use as a dependency.\n // This ensures the useAsync hook only re-runs when the entity changes,\n // preventing redundant API calls during sub-page navigation within the same entity's documentation.\n const entityKey = stringifyEntityRef(entityRef);\n // Track which entity we've already checked to avoid redundant checks\n // when navigating between pages within the same entity's documentation.\n const checkedEntityRef = useRef<string | null>(null);\n const shouldCheckForRedirect = checkedEntityRef.current !== entityKey;\n\n // Check if this entity should redirect to external TechDocs\n const externalRedirectResult = useAsync(async () => {\n try {\n const catalogEntity = await catalogApi.getEntityByRef(entityRef);\n\n if (\n catalogEntity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]\n ) {\n return buildTechDocsURL(catalogEntity, viewTechdocLink);\n }\n } catch (error) {\n // Ignore errors and allow the current entity's TechDocs to load.\n // This handles cases where the catalog API is unavailable or the entity doesn't exist.\n }\n\n return undefined;\n }, [entityKey, catalogApi]);\n\n useEffect(() => {\n // Navigate to external TechDocs if a redirect URL is available\n if (!externalRedirectResult.loading && externalRedirectResult.value) {\n navigate(externalRedirectResult.value, { replace: true });\n }\n\n // Mark entity as checked once we've determined there's no redirect needed.\n // This prevents the entire page from unmounting/remounting (showing Progress spinner)\n // on subsequent sub-page navigation within the same entity.\n if (!externalRedirectResult.loading && !externalRedirectResult.value) {\n checkedEntityRef.current = entityKey;\n }\n }, [\n externalRedirectResult.loading,\n externalRedirectResult.value,\n navigate,\n entityKey,\n ]);\n\n // Determine if we should show a loading indicator (which replaces the entire page with a Progress spinner).\n // Only show it when: 1) checking a new/unchecked entity, or 2) we have a redirect URL and are navigating.\n const shouldShowProgress =\n (shouldCheckForRedirect && externalRedirectResult.loading) ||\n !!externalRedirectResult.value;\n\n return {\n loading: externalRedirectResult.loading,\n shouldShowProgress,\n };\n}\n","/*\n * Copyright 2022 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 { ChangeEvent, useCallback, useMemo } from 'react';\n\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport {\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab/useAutocomplete';\n\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { SearchBar, SearchBarProps } from '../SearchBar';\n\nconst useStyles = makeStyles(theme => ({\n loading: {\n right: theme.spacing(1),\n position: 'absolute',\n },\n}));\n\n/**\n * Props for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteProps<Option> = Omit<\n AutocompleteProps<Option, undefined, undefined, boolean>,\n 'renderInput' | 'disableClearable' | 'multiple'\n> & {\n 'data-testid'?: string;\n inputPlaceholder?: SearchBarProps['placeholder'];\n inputDebounceTime?: SearchBarProps['debounceTime'];\n};\n\n/**\n * Type for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteComponent = <Option>(\n props: SearchAutocompleteProps<Option>,\n) => JSX.Element;\n\nconst withContext = (\n Component: SearchAutocompleteComponent,\n): SearchAutocompleteComponent => {\n return props => (\n <SearchContextProvider inheritParentContextIfAvailable>\n <Component {...props} />\n </SearchContextProvider>\n );\n};\n\nconst SearchAutocompleteLoadingAdornment = () => {\n const classes = useStyles();\n return (\n <CircularProgress\n className={classes.loading}\n data-testid=\"search-autocomplete-progressbar\"\n color=\"inherit\"\n size={20}\n />\n );\n};\n\n/**\n * Recommended search autocomplete when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchAutocomplete = withContext(\n function SearchAutocompleteComponent<Option>(\n props: SearchAutocompleteProps<Option>,\n ) {\n const {\n loading,\n value,\n onChange = () => {},\n options = [],\n getOptionLabel = (option: Option) => String(option),\n inputPlaceholder,\n inputDebounceTime,\n freeSolo = true,\n fullWidth = true,\n clearOnBlur = false,\n 'data-testid': dataTestId = 'search-autocomplete',\n ...rest\n } = props;\n\n const { setTerm } = useSearch();\n\n const getInputValue = useCallback(\n (option?: null | string | Option) => {\n if (!option) return '';\n if (typeof option === 'string') return option;\n return getOptionLabel(option);\n },\n [getOptionLabel],\n );\n\n const inputValue = useMemo(\n () => getInputValue(value),\n [value, getInputValue],\n );\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<{}>,\n option: null | string | Option,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<Option>,\n ) => {\n setTerm(getInputValue(option));\n onChange(event, option, reason, details);\n },\n [getInputValue, setTerm, onChange],\n );\n\n const renderInput = useCallback(\n ({\n InputProps: { ref, className, endAdornment },\n InputLabelProps,\n ...params\n }: AutocompleteRenderInputParams) => (\n <SearchBar\n {...params}\n ref={ref}\n clearButton={false}\n value={inputValue}\n placeholder={inputPlaceholder}\n debounceTime={inputDebounceTime}\n endAdornment={\n loading ? <SearchAutocompleteLoadingAdornment /> : endAdornment\n }\n InputProps={{ className }}\n />\n ),\n [loading, inputValue, inputPlaceholder, inputDebounceTime],\n );\n\n return (\n <Autocomplete\n {...rest}\n data-testid={dataTestId}\n value={value}\n onChange={handleChange}\n options={options}\n getOptionLabel={getOptionLabel}\n renderInput={renderInput}\n freeSolo={freeSolo}\n fullWidth={fullWidth}\n clearOnBlur={clearOnBlur}\n />\n );\n },\n);\n","/*\n * Copyright 2025 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const searchReactTranslationRef = createTranslationRef({\n id: 'search-react',\n messages: {\n searchBar: {\n title: 'Search',\n placeholder: 'Search in {{org}}',\n clearButtonTitle: 'Clear',\n },\n searchFilter: {\n allOptionTitle: 'All',\n },\n searchPagination: {\n limitLabel: 'Results per page:',\n limitText: 'of {{num}}',\n },\n noResultsDescription: 'Sorry, no results were found',\n searchResultGroup: {\n linkTitle: 'See All',\n addFilterButtonTitle: 'Add filter',\n },\n searchResultPager: {\n previous: 'Previous',\n next: 'Next',\n },\n },\n});\n","/*\n * Copyright 2022 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 AnalyticsContext,\n configApiRef,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '@material-ui/core/Button';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport DefaultSearchIcon from '@material-ui/icons/Search';\nimport {\n ReactNode,\n ChangeEvent,\n forwardRef,\n KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchBarBase}.\n *\n * @public\n */\nexport type SearchBarBaseProps = Omit<TextFieldProps, 'onChange'> & {\n debounceTime?: number;\n clearButton?: boolean;\n onClear?: () => void;\n onSubmit?: () => void;\n onChange: (value: string) => void;\n endAdornment?: ReactNode;\n};\n\n/**\n * All search boxes exported by the search plugin are based on the <SearchBarBase />,\n * and this one is based on the <InputBase /> component from Material UI.\n * Recommended if you don't use Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBarBase = forwardRef((props: SearchBarBaseProps, ref) => {\n const {\n onChange,\n onKeyDown = () => {},\n onClear = () => {},\n onSubmit = () => {},\n debounceTime = 200,\n clearButton = true,\n fullWidth = true,\n value: defaultValue,\n label,\n placeholder,\n inputProps = {},\n InputProps = {},\n endAdornment,\n ...rest\n } = props;\n\n const configApi = useApi(configApiRef);\n const [value, setValue] = useState<string>('');\n const forwardedValueRef = useRef<string>('');\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n useEffect(() => {\n setValue(prevValue => {\n // We only update the value if our current value is the same as it was\n // for the most recent onChange call. Otherwise it means that the users\n // has continued typing and we should not replace their input.\n if (prevValue === forwardedValueRef.current) {\n return String(defaultValue);\n }\n return prevValue;\n });\n }, [defaultValue, forwardedValueRef]);\n\n useDebounce(\n () => {\n forwardedValueRef.current = value;\n onChange(value);\n },\n debounceTime,\n [value],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e);\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onKeyDown, onSubmit],\n );\n\n const handleClear = useCallback(() => {\n forwardedValueRef.current = '';\n onChange('');\n setValue('');\n if (onClear) {\n onClear();\n }\n }, [onChange, onClear]);\n\n const ariaLabel: string | undefined = label\n ? undefined\n : t('searchBar.title');\n\n const inputPlaceholder =\n placeholder ??\n t('searchBar.placeholder', {\n org: configApi.getOptionalString('app.title') || 'Backstage',\n });\n const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;\n\n const startAdornment = (\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" size=\"small\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n );\n\n const clearButtonEndAdornment = (\n <InputAdornment position=\"end\">\n <Button\n aria-label={t('searchBar.clearButtonTitle')}\n size=\"small\"\n onClick={handleClear}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n // write your functionality here\n event.stopPropagation();\n }\n }}\n >\n {t('searchBar.clearButtonTitle')}\n </Button>\n </InputAdornment>\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <TextField\n id=\"search-bar-text-field\"\n data-testid=\"search-bar-next\"\n variant=\"outlined\"\n margin=\"normal\"\n inputRef={ref}\n value={value}\n label={label}\n placeholder={inputPlaceholder}\n InputProps={{\n startAdornment,\n endAdornment: clearButton ? clearButtonEndAdornment : endAdornment,\n ...InputProps,\n }}\n inputProps={{\n 'aria-label': ariaLabel,\n ...inputProps,\n }}\n fullWidth={fullWidth}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n </SearchContextProvider>\n );\n});\n\n/**\n * Props for {@link SearchBar}.\n *\n * @public\n */\nexport type SearchBarProps = Partial<SearchBarBaseProps>;\n\n/**\n * Recommended search bar when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBar = forwardRef((props: SearchBarProps, ref) => {\n const { value: initialValue = '', onChange, ...rest } = props;\n\n const { term, setTerm } = useSearch();\n\n useEffect(() => {\n if (initialValue) {\n setTerm(String(initialValue));\n }\n }, [initialValue, setTerm]);\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n } else {\n setTerm(newValue);\n }\n },\n [onChange, setTerm],\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <AnalyticsContext\n attributes={{ pluginId: 'search', extension: 'SearchBar' }}\n >\n <SearchBarBase\n {...rest}\n ref={ref}\n value={term}\n onChange={handleChange}\n />\n </AnalyticsContext>\n </SearchContextProvider>\n );\n});\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport {\n SearchAutocomplete,\n SearchContextProvider,\n} from '@backstage/plugin-search-react';\nimport { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem';\nimport {\n useTechDocsSearch,\n TechDocsSearchResult,\n} from '../../hooks/useTechDocsSearch';\n\n/**\n * Props for {@link TechDocsSearch}\n *\n * @public\n */\nexport type TechDocsSearchProps = {\n entityId: CompoundEntityRef;\n entityTitle?: string;\n debounceTime?: number;\n searchResultUrlMapper?: (url: string) => string;\n};\n\nconst isTechDocsSearchResult = (\n option: any,\n): option is TechDocsSearchResult => {\n return option?.document;\n};\n\nconst TechDocsSearchBar = (props: TechDocsSearchProps) => {\n const {\n entityId,\n entityTitle,\n debounceTime = 150,\n searchResultUrlMapper,\n } = props;\n const [open, setOpen] = useState(false);\n const navigate = useNavigate();\n const { results, term, loading } = useTechDocsSearch(entityId);\n\n const handleSelection = (\n _: any,\n selection: TechDocsSearchResult | string | null,\n ) => {\n if (isTechDocsSearchResult(selection)) {\n const { location } = selection.document;\n navigate(\n searchResultUrlMapper ? searchResultUrlMapper(location) : location,\n );\n }\n };\n\n return (\n <SearchAutocomplete\n data-testid=\"techdocs-search-bar\"\n size=\"small\"\n open={open && Boolean(term)}\n getOptionLabel={() => ''}\n filterOptions={x => {\n return x; // This is needed to get renderOption to be called after options change. Bug in material-ui?\n }}\n onClose={() => {\n setOpen(false);\n }}\n onOpen={() => {\n setOpen(true);\n }}\n onChange={handleSelection}\n blurOnSelect\n noOptionsText=\"No results found\"\n value={null}\n options={results}\n renderOption={({ document, highlight }) => (\n <TechDocsSearchResultListItem\n result={document}\n lineClamp={3}\n asListItem={false}\n asLink={false}\n title={document.title}\n highlight={highlight}\n />\n )}\n loading={loading}\n inputDebounceTime={debounceTime}\n inputPlaceholder={`Search ${entityTitle || entityId.name} docs`}\n freeSolo={false}\n />\n );\n};\n\n/**\n * Component used to render search bar on TechDocs page, scoped to\n *\n * @public\n */\nexport const TechDocsSearch = (props: TechDocsSearchProps) => {\n const initialState = {\n term: '',\n types: ['techdocs'],\n pageCursor: '',\n filters: props.entityId,\n };\n return (\n <SearchContextProvider initialState={initialState}>\n <TechDocsSearchBar {...props} />\n </SearchContextProvider>\n );\n};\n","/*\n * Copyright 2022 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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Content, Progress } from '@backstage/core-components';\n\nimport { TechDocsSearch } from '../../../search';\nimport { TechDocsStateIndicator } from '../TechDocsStateIndicator';\n\nimport { withTechDocsReaderProvider } from '../TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';\nimport { useTechDocsReaderContentData } from '../../../hooks/useTechDocsReaderContentData';\n\nconst useStyles = makeStyles({\n search: {\n width: '100%',\n '@media (min-width: 76.1875em)': {\n width: 'calc(100% - 34.4rem)',\n margin: '0 auto',\n },\n '@media print': {\n display: 'none',\n },\n },\n});\n\n/**\n * Props for {@link TechDocsReaderPageContent}\n * @public\n */\nexport type TechDocsReaderPageContentProps = {\n /**\n * @deprecated No need to pass down entityRef as property anymore. Consumes the entityName from `TechDocsReaderPageContext`. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom reader page content.\n */\n entityRef?: CompoundEntityRef;\n /**\n * Path in the docs to render by default. This should be used when rendering docs for an entity that specifies the\n * \"backstage.io/techdocs-entity-path\" annotation for deep linking into another entities docs.\n */\n defaultPath?: string;\n /**\n * Show or hide the search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,\n * this will redirect the search result urls, e.g. turn search results into\n * links within the \"Docs\" tab of the entity page, instead of the global docs\n * page.\n */\n searchResultUrlMapper?: (url: string) => string;\n /**\n * Callback called when the content is rendered.\n */\n onReady?: () => void;\n};\n\n/**\n * Renders the reader page content\n * @public\n */\nexport const TechDocsReaderPageContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const { withSearch = true, searchResultUrlMapper } = props;\n const classes = useStyles();\n\n const {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n </Grid>\n </Content>\n );\n }\n\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n {withSearch && (\n <Grid className={classes.search} xs=\"auto\" item>\n <TechDocsSearch\n entityId={entityRef}\n entityTitle={entityMetadata?.metadata?.title}\n searchResultUrlMapper={searchResultUrlMapper}\n />\n </Grid>\n )}\n <Grid xs={12} item>\n {showProgress && <Progress />}\n\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </Grid>\n </Grid>\n </Content>\n );\n },\n);\n\n/**\n * Props for {@link Reader}\n *\n * @public\n * @deprecated use `TechDocsReaderPageContentProps` instead.\n */\nexport type ReaderProps = TechDocsReaderPageContentProps;\n\n/**\n * Component responsible for rendering TechDocs documentation\n * @public\n * @deprecated use `TechDocsReaderPageContent` component instead.\n */\nexport const Reader = TechDocsReaderPageContent;\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 { PropsWithChildren, ReactNode } from 'react';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { Link } from '@backstage/core-components';\nimport { ResultHighlight } from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '@backstage/plugin-search-react';\n\nconst useStyles = makeStyles({\n flexContainer: {\n flexWrap: 'wrap',\n },\n itemText: {\n width: '100%',\n marginBottom: '1rem',\n },\n});\n\n/**\n * Props for {@link TechDocsSearchResultListItem}.\n *\n * @public\n */\nexport type TechDocsSearchResultListItemProps = {\n icon?: ReactNode | ((result: any) => ReactNode);\n result?: any;\n highlight?: ResultHighlight;\n rank?: number;\n lineClamp?: number;\n asListItem?: boolean;\n asLink?: boolean;\n title?: string;\n};\n\n/**\n * Component which renders documentation and related metadata.\n *\n * @public\n */\nexport const TechDocsSearchResultListItem = (\n props: TechDocsSearchResultListItemProps,\n) => {\n const {\n result,\n highlight,\n lineClamp = 5,\n asListItem = true,\n asLink = true,\n title,\n icon,\n } = props;\n const classes = useStyles();\n\n const LinkWrapper = ({ children }: PropsWithChildren<{}>) =>\n asLink ? (\n <Link noTrack to={result.location}>\n {children}\n </Link>\n ) : (\n <>{children}</>\n );\n\n const TextItem = () => {\n const resultTitle = highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight.fields.title}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.title\n );\n\n const entityTitle = highlight?.fields.entityTitle ? (\n <HighlightedSearchResultText\n text={highlight.fields.entityTitle}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.entityTitle\n );\n\n const resultName = highlight?.fields.name ? (\n <HighlightedSearchResultText\n text={highlight.fields.name}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.name\n );\n\n if (!result) return null;\n\n return (\n <ListItemText\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n primary={\n <LinkWrapper>\n {title ? (\n title\n ) : (\n <>\n {resultTitle} | {entityTitle ?? resultName} docs\n </>\n )}\n </LinkWrapper>\n }\n secondary={\n <Typography\n component=\"span\"\n style={{\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lineClamp,\n overflow: 'hidden',\n }}\n color=\"textSecondary\"\n variant=\"body2\"\n >\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </Typography>\n }\n />\n );\n };\n\n const ListItemWrapper = ({ children }: PropsWithChildren<{}>) =>\n asListItem ? (\n <>\n {icon && (\n <ListItemIcon>\n {typeof icon === 'function' ? icon(result) : icon}\n </ListItemIcon>\n )}\n <div className={classes.flexContainer}>{children}</div>\n </>\n ) : (\n <>{children}</>\n );\n\n return (\n <ListItemWrapper>\n <TextItem />\n </ListItemWrapper>\n );\n};\n"],"names":["useStyles","makeStyles","EmptyStateImage","missing","classes","missingAnnotation","noInformation","createComponent","noBuild","theme","EmptyState","props","title","description","action","Grid","Typography","FavoriteToggleIcon","isFavorite","StarIcon","UnstarredIcon","FavoriteToggle","id","value","onChange","iconButtonProps","Tooltip","IconButton","createStyles","SvgIcon","BootstrapInput","withStyles","InputBase","SelectComponent","multiple","items","label","placeholder","selected","triggerReset","native","disabled","margin","dataTestId","setValue","useState","isOpen","setOpen","useEffect","Box","FormControl","InputLabel","Select","event","previous","HTMLElement","s","selectedValue","item","el","Chip","CancelIcon","newValue","chip","OpenedDropdown","ClosedDropdown","MenuItem","Checkbox","useFilterStyles","Filters","onChangeFilters","t","useTranslationRef","coreComponentsTranslationRef","selectedFilters","setSelectedFilters","reset","Button","filter","TableLoadingBody","CircularProgress","tableIcons","forwardRef","ref","AddBox","Check","Clear","DeleteOutline","ChevronRight","Edit","SaveAlt","FilterList","FirstPage","LastPage","ChevronLeft","Search","ArrowUpward","Remove","ViewColumn","extractValueByField","data","field","path","i","undefined","StyledMTableHeader","MTableHeader","StyledMTableToolbar","MTableToolbar","useTableStyles","defaultInitialState","TableToolbar","toolbarProps","toolbarRef","setSearch","hasFilters","selectedFiltersLength","toggleFilters","filtersClasses","onSearchChanged","useCallback","searchText","Table","filterConfig","dataValue","columns","emptyContent","options","subtitle","localization","filters","initialState","onStateChange","components","loading","style","restProps","tableClasses","useTheme","calculatedInitialState","filtersOpen","setFiltersOpen","v","search","state","transform","result","key","isEqual","defaultState","getFieldByTitle","titleValue","tableData","useMemo","selectedFiltersArray","Object","filterValue","fieldValue","Array","Toolbar","hasNoRows","columnCount","Body","makeBody","bodyProps","MTableBody","distinctValues","addValue","Set","c","MTable","column","headerStyle","cellStyle","cellStyleFn","rowData","rowColumn","alpha","HeaderLabelContent","className","typographyRootComponent","HeaderLabel","url","contentTypograpyRootComponent","content","Link","entityPresentationSnapshot","entityOrRef","context","entityPresentationApi","stringifyEntityRef","defaultEntityPresentation","BootstrapAutocomplete","Autocomplete","PopperComponent","Popper","TransitionProps","Grow","PaperComponent","Paper","CatalogAutocomplete","name","LabelProps","TextFieldProps","rest","renderInput","params","TextField","merge","autocomplete","ExpandMoreIcon","classNames","CatalogFilterLayout","isScreenSmallerThanBreakpoint","useMediaQuery","filterDrawerOpen","setFilterDrawerOpen","catalogReactTranslationRef","FilterListIcon","Drawer","icon","CheckBoxOutlineBlankIcon","checkedIcon","CheckBoxIcon","OptionCheckbox","EntityAutocompletePickerOption","memo","availableOptions","showCounts","FormControlLabel","EntityAutocompletePicker","Filter","InputProps","initialSelectedOptions","filtersForAvailableValues","hidden","updateFilters","queryParameter","useEntityList","catalogApi","useApi","catalogApiRef","availableValuesFilters","f","availableValues","useAsync","facets","reduceBackendCatalogFilters","Boolean","count","queryParameters","filteredOptions","selectedOptions","setSelectedOptions","shouldAddFilter","newSelectedOptions","String","_event","option","FixedWidthFormControlLabel","_theme","RenderOptionLabel","isGroup","useEntityPresentation","GroupIcon","PersonIcon","EntityOwnerPicker","mode","apis","useApiHolder","entityPresentationApiRef","ownersParameter","text","setText","queryParamOwners","selectedOwners","setSelectedOwners","handleFetch","cache","useFetchEntities","initialSelectedOwnersRefs","isOwnersOnlyMode","queryEntitiesResponse","useAsyncFn","request","limit","cursorRequest","response","initialRequest","facetsEntitiesResponse","useFacetsEntities","enabled","facetsPromise","facet","e","kind","namespace","parseEntityRef","a","b","start","isFacetsResponse","JSON","atob","filteredRefs","entity","normalizedText","end","encodeCursor","entities","payload","btoa","useSelectedOwners","allEntities","useRef","initialSelectedEntities","useMountEffect","entityRef","useDebouncedEffect","availableOwners","EntityOwnerFilter","o","_","owners","x","_e","inputValue","element","hasReachedEnd","Math","EntityTagPicker","EntityTagFilter","UserListPicker","initialFilter","availableFilters","alwaysKeepFilters","configApi","configApiRef","orgName","userParameter","kindParameter","userAndGroupFilterIds","filterGroups","getFilterGroups","SettingsIcon","filterGroup","ownedEntitiesCount","loadingOwnedEntities","ownedEntitiesFilter","useOwnedEntitiesCount","identityApi","identityApiRef","ownershipEntityRefs","loadingEntityRefs","user","allFilters","orderFields","catalogFilters","reduceCatalogFilters","compact","loadingEntityOwnership","fetchEntities","req","ownedClaims","getOwnedCountClaims","ownersRefs","commonOwnedBy","intersection","metadata","totalItems","useDeepCompareEffect","EntityUserFilter","allCount","useAllEntitiesCount","prevRequest","compacted","newRequest","starredEntitiesCount","starredEntitiesFilter","loadingStarredEntities","useStarredEntitiesCount","starredEntities","useStarredEntities","queryParamUserFilter","selectedUserFilter","setSelectedUserFilter","filterCounts","Card","group","Fragment","List","index","ListItemIcon","ListItemText","ListItemSecondaryAction","EntityKindFilter","EntityTypeFilter","values","EntityTextFilter","words","exactMatch","partialMatch","word","m","fullRefs","err","getEntityRelations","RELATION_OWNED_BY","EntityLifecycleFilter","EntityNamespaceFilter","refs","starredEntityRefs","relations","UserListFilter","isOwnedEntity","isStarredEntity","EntityOrphanFilter","orphan","EntityErrorFilter","error","NewEntityListContext","createVersionedContext","OldEntityListContext","createContext","EntityListProvider","isMounted","useMountedState","requestedFilters","setRequestedFilters","location","useLocation","paginationMode","paginationLimit","initialCursor","initialOffset","initialLimit","parsed","qs","queryLimit","Number","isNaN","offset","cursor","setCursor","setOffset","setLimit","outputState","setOutputState","resolvedValue","refresh","kindValue","adjustedFilters","entityFilter","reduceEntityFilters","backendFilter","previousBackendFilter","useDebounce","queryParams","oldParams","newParams","newUrl","window","document","update","prevFilters","newFilters","latestOutput","pageInfo","prevCursor","nextCursor","createVersionedValueMap","versionedHolder","useVersionedContext","oldContext","useContext","Error","getEntityRef","starredEntitiesApi","starredEntitiesApiRef","useObservable","toggleStarredEntity","isEntityTextFilter","isEntityOrderFilter","condensedFilters","compoundFilter","fullTextFilter","backendCatalogFilters","techdocsPlugin","PluginImpl","config","extension","createApiFactory","techdocsStorageApiRef","discoveryApiRef","fetchApiRef","discoveryApi","fetchApi","TechDocsStorageClient","techdocsApiRef","TechDocsClient","rootRouteRef","rootDocsRouteRef","rootCatalogDocsRouteRef","createRoutableExtension","TechDocsReaderPage","createSearchResultListItemExtension","EntityPageDocs","withSearch","getCompoundEntityRef","searchResultUrlMapper","useEntityPageTechDocsRedirect","routeDocsRoot","useRouteRef","routeDocsCatalog","rootDocsPath","catalogDocsPath","suffix","TECHDOCS_EXTERNAL_ANNOTATION","defaultPath","getEntityRootTechDocsPath","TechDocsReaderPageSubheader","TechDocsReaderPageContent","MissingAnnotationEmptyState","type","owner","yamlText","line","lineNumbers","entityContext","useEntity","annotation","readMoreUrl","annotations","entityKind","ann","generateDescription","annotationList","prev","curr","CodeSnippet","Router","Routes","Route","TechDocsIndexPage","TechDocsReaderRouter","children","useRoutes","EmbeddedDocsRouter","emptyState","TECHDOCS_ANNOTATION","LegacyEmbeddedDocsRouter","toLowerMaybe","str","DocsTable","actions","copyToClipboard","useCopyToClipboard","getRouteToReaderPageFor","documents","entitiesToDocsMapper","defaultActions","actionFactories","paging","pageSize","defaultColumns","LinkButton","columnFactories","OffsetPaginatedDocsTable","isLoading","page","setPage","newPage","CursorPaginatedDocsTable","next","EntityListDocsTable","capitalize","WarningPanel","row","ShareIcon","isStarred","useSubvalueCellStyles","SubvalueCell","subvalue","customTitle","row1","row2","title1","title2","resolved","EntityRefLinks","ownedByRelations","r","DefaultTechDocsHome","ownerPickerMode","pagination","PageWrapper","CustomHeader","Wrapper","TechDocsPageWrapper","Header","ContentHeader","SupportButton","Content","TechDocsPicker","outlet","useOutlet","PageWithHeader","themeId","Page","CustomPageWrapper","generatedSubtitle","TechDocsFilter","CATALOG_FILTER_EXISTS","skeleton","Skeleton","TechDocsReaderPageHeader","entityMetadata","tabTitle","showSourceLink","sourceLink","addons","useTechDocsReaderHeaderData","docsRootLink","spec","lifecycle","labels","EntityRefLink","CodeIcon","Helmet","locations","CookieAuthRefreshProvider","Progress","app","useApp","useCookieAuthRefresh","pluginId","channel","BroadcastChannel","apiOrigin","requestUrl","Date","ResponseError","retry","timeout","setTimeout","clearTimeout","cancel","listener","ErrorPanel","TechDocsReaderLayout","withHeader","StyledPage","styled","navigate","viewTechdocLink","entityKey","checkedEntityRef","shouldCheckForRedirect","externalRedirectResult","shouldShowProgress","currentTheme","readerPageTheme","createTheme","useRouteRefParams","memoizedEntityRef","useNavigate","catalogEntity","buildTechDocsURL","grandChildren","childrenList","Children","child","grandChild","getComponentData","TECHDOCS_ADDONS_WRAPPER_KEY","TECHDOCS_ADDONS_KEY","ThemeProvider","TechDocsReaderPageProvider","onReady","Function","Component","searchReactTranslationRef","createTranslationRef","SearchBarBase","onKeyDown","onClear","onSubmit","debounceTime","clearButton","fullWidth","defaultValue","inputProps","endAdornment","forwardedValueRef","prevValue","handleChange","handleKeyDown","handleClear","ariaLabel","inputPlaceholder","SearchIcon","DefaultSearchIcon","startAdornment","InputAdornment","clearButtonEndAdornment","SearchContextProvider","SearchBar","initialValue","term","setTerm","useSearch","AnalyticsContext","SearchAutocompleteLoadingAdornment","SearchAutocomplete","getOptionLabel","inputDebounceTime","freeSolo","clearOnBlur","getInputValue","reason","details","InputLabelProps","TechDocsSearchBar","entityId","entityTitle","open","results","useTechDocsSearch","selection","highlight","TechDocsSearchResultListItem","TechDocsSearch","withTechDocsReaderProvider","dom","handleAppend","isNotFound","isDomReady","showProgress","NotFoundErrorPage","useTechDocsReaderContentData","TechDocsStateIndicator","TechDocsShadowDom","TechDocsReaderPageContentAddons","lineClamp","asListItem","asLink","LinkWrapper","ListItemWrapper","resultTitle","HighlightedSearchResultText","resultName","TextItem"],"mappings":"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"}
1
+ {"version":3,"file":"static/8461.0c3f2ac0.chunk.js","sources":["webpack://techdocs-cli-embedded-app/../../node_modules/@material-ui/icons/Share.js","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyStateImage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/EmptyState/EmptyState.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/FavoriteToggle/FavoriteToggle.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/ClosedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/static/OpenedDropdown.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Select/Select.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Filters.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/TableLoadingBody.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/Table.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/HeaderLabel/HeaderLabel.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/apis/EntityPresentationApi/entityPresentationSnapshot.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogAutocomplete/CatalogAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/CatalogFilterLayout/CatalogFilterLayout.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePickerOption.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityAutocompletePicker/EntityAutocompletePicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFetchEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useQueryEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityOwnerPicker/useFacetsEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useOwnedEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useAllEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/UserListPicker/useStarredEntitiesCount.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useEntityListProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/hooks/useStarredEntities.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/utils/filters.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/plugin.ts","webpack://techdocs-cli-embedded-app/../core-plugin-api/src/plugin/Plugin.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/EntityPageDocs.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/hooks/useTechDocsLocation.ts","webpack://techdocs-cli-embedded-app/../../plugins/catalog-react/src/components/MissingAnnotationEmptyState/MissingAnnotationEmptyState.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/Router.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/DocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/OffsetPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/CursorPaginatedDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/EntityListDocsTable.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/actions.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/components/Table/SubvalueCell.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/columns.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/Tables/helpers.ts","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/DefaultTechDocsHome.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsIndexPage.tsx","webpack://techdocs-cli-embedded-app/../core-components/src/layout/Page/PageWithHeader.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPageWrapper.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/home/components/TechDocsPicker.tsx","webpack://techdocs-cli-embedded-app/../../node_modules/@material-ui/lab/esm/Skeleton/Skeleton.js","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageHeader/TechDocsReaderPageHeader.tsx","webpack://techdocs-cli-embedded-app/../../plugins/auth-react/src/components/CookieAuthRefreshProvider/CookieAuthRefreshProvider.tsx","webpack://techdocs-cli-embedded-app/../../plugins/auth-react/src/hooks/useCookieAuthRefresh/useCookieAuthRefresh.tsx","webpack://techdocs-cli-embedded-app/../../node_modules/@react-hookz/web/src/useAsync/index.js","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPage/TechDocsReaderPage.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPage/useExternalRedirect.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchAutocomplete/SearchAutocomplete.tsx","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/translation.ts","webpack://techdocs-cli-embedded-app/../../plugins/search-react/src/components/SearchBar/SearchBar.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearch.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/reader/components/TechDocsReaderPageContent/TechDocsReaderPageContent.tsx","webpack://techdocs-cli-embedded-app/../../plugins/techdocs/src/search/components/TechDocsSearchResultListItem.tsx"],"sourcesContent":["\"use strict\";\n\nvar _interopRequireDefault = require(\"@babel/runtime/helpers/interopRequireDefault\");\n\nvar _interopRequireWildcard = require(\"@babel/runtime/helpers/interopRequireWildcard\");\n\nObject.defineProperty(exports, \"__esModule\", {\n value: true\n});\nexports.default = void 0;\n\nvar React = _interopRequireWildcard(require(\"react\"));\n\nvar _createSvgIcon = _interopRequireDefault(require(\"./utils/createSvgIcon\"));\n\nvar _default = (0, _createSvgIcon.default)( /*#__PURE__*/React.createElement(\"path\", {\n d: \"M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z\"\n}), 'Share');\n\nexports.default = _default;","/*\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 missingAnnotation from './assets/missingAnnotation.svg';\nimport noInformation from './assets/noInformation.svg';\nimport createComponent from './assets/createComponent.svg';\nimport noBuild from './assets/noBuild.svg';\nimport { makeStyles } from '@material-ui/core/styles';\n\ntype Props = {\n missing: 'field' | 'info' | 'content' | 'data';\n};\n\n/** @public */\nexport type EmptyStateImageClassKey = 'generalImg';\n\nconst useStyles = makeStyles(\n {\n generalImg: {\n width: '95%',\n zIndex: 2,\n position: 'relative',\n left: '50%',\n top: '50%',\n transform: 'translate(-50%, 15%)',\n },\n },\n { name: 'BackstageEmptyStateImage' },\n);\n\n/** @public */\nexport const EmptyStateImage = ({ missing }: Props) => {\n const classes = useStyles();\n switch (missing) {\n case 'field':\n return (\n <img\n src={missingAnnotation}\n className={classes.generalImg}\n alt=\"annotation is missing\"\n />\n );\n case 'info':\n return (\n <img\n src={noInformation}\n alt=\"no Information\"\n className={classes.generalImg}\n />\n );\n case 'content':\n return (\n <img\n src={createComponent}\n alt=\"create Component\"\n className={classes.generalImg}\n />\n );\n case 'data':\n return (\n <img src={noBuild} alt=\"no Build\" className={classes.generalImg} />\n );\n default:\n return null;\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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { EmptyStateImage } from './EmptyStateImage';\n\n/** @public */\nexport type EmptyStateClassKey = 'root' | 'action' | 'imageContainer';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: theme.palette.background.default,\n padding: theme.spacing(2, 0, 0, 0),\n },\n action: {\n marginTop: theme.spacing(2),\n },\n imageContainer: {\n position: 'relative',\n },\n }),\n { name: 'BackstageEmptyState' },\n);\n\ntype Props = {\n title: string;\n description?: string | JSX.Element;\n missing: 'field' | 'info' | 'content' | 'data' | { customImage: JSX.Element };\n action?: JSX.Element;\n};\n\n/**\n * Various placeholder views for empty state pages\n *\n * @public\n *\n */\nexport function EmptyState(props: Props) {\n const { title, description, missing, action } = props;\n const classes = useStyles();\n return (\n <Grid\n container\n direction=\"row\"\n justifyContent=\"space-around\"\n alignItems=\"flex-start\"\n className={classes.root}\n spacing={2}\n >\n <Grid item xs={12} md={6}>\n <Grid container direction=\"column\">\n <Grid item xs>\n <Typography variant=\"h5\">{title}</Typography>\n </Grid>\n <Grid item xs>\n <Typography variant=\"body1\">{description}</Typography>\n </Grid>\n <Grid item xs className={classes.action}>\n {action}\n </Grid>\n </Grid>\n </Grid>\n <Grid item xs={12} md={6} className={classes.imageContainer}>\n {typeof missing === 'string' ? (\n <EmptyStateImage missing={missing} />\n ) : (\n missing.customImage\n )}\n </Grid>\n </Grid>\n );\n}\n","/*\n * Copyright 2024 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 { ComponentProps } from 'react';\nimport IconButton from '@material-ui/core/IconButton';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport Typography from '@material-ui/core/Typography';\nimport { Theme, makeStyles } from '@material-ui/core/styles';\nimport { StarIcon, UnstarredIcon } from '../../icons';\n\nconst useStyles = makeStyles<Theme>(\n () => ({\n icon: {\n color: '#f3ba37',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n iconBorder: {\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n },\n }),\n { name: 'BackstageFavoriteToggleIcon' },\n);\n\n/**\n * @public\n */\nexport type FavoriteToggleIconClassKey = 'icon' | 'iconBorder';\n\n/**\n * Icon used in FavoriteToggle component.\n *\n * Can be used independently, useful when used as {@link @material-table/core#MaterialTableProps.actions} in {@link @material-table/core#MaterialTable}\n *\n * @public\n */\nexport function FavoriteToggleIcon(props: { isFavorite: boolean }) {\n const { isFavorite } = props;\n const classes = useStyles();\n\n return (\n <Typography\n component=\"span\"\n className={isFavorite ? classes.icon : classes.iconBorder}\n >\n {isFavorite ? <StarIcon /> : <UnstarredIcon />}\n </Typography>\n );\n}\n\n/**\n * Props for the {@link FavoriteToggle} component.\n *\n * @public\n */\nexport type FavoriteToggleProps = ComponentProps<typeof IconButton> & {\n id: string;\n title: string;\n isFavorite: boolean;\n onToggle: (value: boolean) => void;\n};\n\n/**\n * Toggle encapsulating logic for marking something as favorite,\n * primarily used in various instances of entity lists and cards but can be used elsewhere.\n *\n * This component can only be used in as a controlled toggle and does not keep internal state.\n *\n * @public\n */\nexport function FavoriteToggle(props: FavoriteToggleProps) {\n const {\n id,\n title,\n isFavorite: value,\n onToggle: onChange,\n ...iconButtonProps\n } = props;\n return (\n <Tooltip id={id} title={title}>\n <IconButton\n aria-label={title}\n id={id}\n onClick={() => onChange(!value)}\n color=\"inherit\"\n {...iconButtonProps}\n >\n <FavoriteToggleIcon isFavorite={value} />\n </IconButton>\n </Tooltip>\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 { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\n/** @public */\nexport type ClosedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageClosedDropdown' },\n);\n\nconst ClosedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M7.5 8L6 9.5L12.0703 15.5703L18.1406 9.5L16.6406 8L12.0703 12.5703L7.5 8Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default ClosedDropdown;\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 { makeStyles, createStyles } from '@material-ui/core/styles';\nimport SvgIcon from '@material-ui/core/SvgIcon';\n\nexport type OpenedDropdownClassKey = 'icon';\n\nconst useStyles = makeStyles(\n theme =>\n createStyles({\n icon: {\n position: 'absolute',\n right: theme.spacing(0.5),\n pointerEvents: 'none',\n color: '#616161',\n },\n }),\n { name: 'BackstageOpenedDropdown' },\n);\n\nconst OpenedDropdown = () => {\n const classes = useStyles();\n return (\n <SvgIcon\n className={classes.icon}\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path\n d=\"M16.5 16L18 14.5L11.9297 8.42969L5.85938 14.5L7.35938 16L11.9297 11.4297L16.5 16Z\"\n fill=\"currentColor\"\n />\n </SvgIcon>\n );\n};\n\nexport default OpenedDropdown;\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 Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport Chip from '@material-ui/core/Chip';\nimport FormControl from '@material-ui/core/FormControl';\nimport InputBase from '@material-ui/core/InputBase';\nimport InputLabel from '@material-ui/core/InputLabel';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Select from '@material-ui/core/Select';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport { ChangeEvent, useEffect, useState } from 'react';\n\nimport ClosedDropdown from './static/ClosedDropdown';\nimport OpenedDropdown from './static/OpenedDropdown';\n\n/** @public */\nexport type SelectInputBaseClassKey = 'root' | 'input';\n\nconst BootstrapInput = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {\n 'label + &': {\n marginTop: theme.spacing(3),\n },\n '&.Mui-focused > div[role=button]': {\n borderColor: theme.palette.primary.main,\n },\n },\n input: {\n borderRadius: theme.shape.borderRadius,\n position: 'relative',\n backgroundColor: theme.palette.background.paper,\n border: '1px solid #ced4da',\n fontSize: theme.typography.body1.fontSize,\n padding: theme.spacing(1.25, 3.25, 1.25, 1.5),\n transition: theme.transitions.create(['border-color', 'box-shadow']),\n '&:focus': {\n background: theme.palette.background.paper,\n borderRadius: theme.shape.borderRadius,\n },\n },\n }),\n { name: 'BackstageSelectInputBase' },\n)(InputBase);\n\n/** @public */\nexport type SelectClassKey =\n | 'formControl'\n | 'label'\n | 'chips'\n | 'chip'\n | 'checkbox'\n | 'root';\n\nconst useStyles = makeStyles(\n (theme: Theme) =>\n createStyles({\n formControl: {\n margin: theme.spacing(1, 0),\n },\n label: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n formLabel: {\n transform: 'initial',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '&.Mui-focused': {\n color: theme.palette.text.primary,\n },\n },\n chips: {\n display: 'flex',\n flexWrap: 'wrap',\n },\n chip: {\n margin: 2,\n },\n checkbox: {},\n\n root: {\n display: 'flex',\n flexDirection: 'column',\n },\n }),\n { name: 'BackstageSelect' },\n);\n\n/** @public */\nexport type SelectItem = {\n label: string;\n value: string | number;\n};\n\n/** @public */\nexport type SelectedItems = string | string[] | number | number[];\n\nexport type SelectProps = {\n multiple?: boolean;\n items: SelectItem[];\n label: string;\n placeholder?: string;\n selected?: SelectedItems;\n onChange: (arg: SelectedItems) => void;\n triggerReset?: boolean;\n native?: boolean;\n disabled?: boolean;\n margin?: 'dense' | 'none';\n 'data-testid'?: string;\n};\n\n/** @public */\nexport function SelectComponent(props: SelectProps) {\n const {\n multiple,\n items,\n label,\n placeholder,\n selected,\n onChange,\n triggerReset,\n native = false,\n disabled = false,\n margin,\n 'data-testid': dataTestId = 'select',\n } = props;\n const classes = useStyles();\n const [value, setValue] = useState<SelectedItems>(\n selected || (multiple ? [] : ''),\n );\n const [isOpen, setOpen] = useState(false);\n\n useEffect(() => {\n setValue(multiple ? [] : '');\n }, [triggerReset, multiple]);\n\n useEffect(() => {\n setValue(selected || (multiple ? [] : ''));\n }, [selected, multiple]);\n\n const handleChange = (event: ChangeEvent<{ value: unknown }>) => {\n setValue(event.target.value as SelectedItems);\n onChange(event.target.value as SelectedItems);\n };\n\n const handleOpen = (event: ChangeEvent<any>) => {\n if (disabled) {\n event.preventDefault();\n return;\n }\n setOpen(previous => {\n if (multiple && !(event.target instanceof HTMLElement)) {\n return true;\n }\n return !previous;\n });\n };\n\n const handleClose = () => {\n setOpen(false);\n };\n\n const handleDelete = (selectedValue: string | number) => () => {\n const newValue = (value as any[]).filter(chip => chip !== selectedValue);\n setValue(newValue);\n onChange(newValue);\n };\n\n return (\n <Box className={classes.root}>\n <FormControl className={classes.formControl}>\n <InputLabel className={classes.formLabel}>{label}</InputLabel>\n <Select\n aria-label={label}\n value={value}\n native={native}\n disabled={disabled}\n data-testid={dataTestId}\n displayEmpty\n multiple={multiple}\n margin={margin}\n onChange={handleChange}\n open={isOpen}\n onOpen={handleOpen}\n onClose={handleClose}\n input={<BootstrapInput />}\n label={label}\n renderValue={s =>\n multiple && (value as any[]).length !== 0 ? (\n <Box className={classes.chips}>\n {(s as string[]).map(selectedValue => {\n const item = items.find(el => el.value === selectedValue);\n return item ? (\n <Chip\n data-testid=\"chip\"\n key={item?.value}\n label={item?.label}\n clickable\n deleteIcon={\n <CancelIcon\n data-testid=\"cancel-icon\"\n onMouseDown={event => event.stopPropagation()}\n />\n }\n onDelete={handleDelete(selectedValue)}\n className={classes.chip}\n />\n ) : (\n false\n );\n })}\n </Box>\n ) : (\n <Typography>\n {(value as any[]).length === 0\n ? placeholder || ''\n : items.find(el => el.value === s)?.label}\n </Typography>\n )\n }\n IconComponent={() =>\n !isOpen ? <ClosedDropdown /> : <OpenedDropdown />\n }\n MenuProps={{\n anchorOrigin: {\n vertical: 'bottom',\n horizontal: 'left',\n },\n transformOrigin: {\n vertical: 'top',\n horizontal: 'left',\n },\n getContentAnchorEl: null,\n }}\n >\n {!!placeholder && !multiple && (\n <MenuItem value={[]}>{placeholder}</MenuItem>\n )}\n {native\n ? items &&\n items.map(item => (\n <option value={item.value} key={item.value}>\n {item.label}\n </option>\n ))\n : items &&\n items.map(item => (\n <MenuItem key={item.value} value={item.value}>\n {multiple && (\n <Checkbox\n color=\"primary\"\n checked={(value as any[]).includes(item.value) || false}\n className={classes.checkbox}\n />\n )}\n {item.label}\n </MenuItem>\n ))}\n </Select>\n </FormControl>\n </Box>\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 Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useState } from 'react';\n\nimport { Select } from '../Select';\nimport { SelectProps } from '../Select/Select';\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\nexport type TableFiltersClassKey = 'root' | 'value' | 'heder' | 'filters';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n height: '100%',\n width: '315px',\n display: 'flex',\n flexDirection: 'column',\n marginRight: theme.spacing(3),\n },\n value: {\n fontWeight: 'bold',\n fontSize: 18,\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n height: theme.spacing(7.5),\n justifyContent: 'space-between',\n borderBottom: `1px solid ${theme.palette.grey[500]}`,\n },\n filters: {\n display: 'flex',\n flexDirection: 'column',\n '& > *': {\n marginTop: theme.spacing(2),\n },\n },\n }),\n { name: 'BackstageTableFilters' },\n);\n\nexport type Without<T, K> = Pick<T, Exclude<keyof T, K>>;\n\nexport type Filter = {\n type: 'select' | 'multiple-select';\n element: Without<SelectProps, 'onChange'>;\n};\n\nexport type SelectedFilters = {\n [key: string]: string | string[];\n};\n\ntype Props = {\n filters: Filter[];\n selectedFilters?: SelectedFilters;\n onChangeFilters: (arg: any) => any;\n};\n\nexport const Filters = (props: Props) => {\n const classes = useFilterStyles();\n\n const { onChangeFilters } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n\n const [selectedFilters, setSelectedFilters] = useState<SelectedFilters>({\n ...props.selectedFilters,\n });\n const [reset, triggerReset] = useState(false);\n\n // Trigger re-rendering\n const handleClick = () => {\n setSelectedFilters({});\n triggerReset(el => !el);\n };\n\n useEffect(() => {\n onChangeFilters(selectedFilters);\n }, [selectedFilters, onChangeFilters]);\n\n // As material table doesn't provide a way to add a column filter tab we will make our own filter logic\n return (\n <Box className={classes.root}>\n <Box className={classes.header}>\n <Box className={classes.value}>{t('table.filter.title')}</Box>\n <Button color=\"primary\" onClick={handleClick}>\n {t('table.filter.clearAll')}\n </Button>\n </Box>\n <Box className={classes.filters}>\n {props.filters?.length &&\n props.filters.map(filter => (\n <Select\n triggerReset={reset}\n key={filter.element.label}\n {...(filter.element as SelectProps)}\n selected={selectedFilters[filter.element.label]}\n onChange={el =>\n setSelectedFilters({\n ...selectedFilters,\n [filter.element.label]: el as any,\n })\n }\n />\n ))}\n </Box>\n </Box>\n );\n};\n","/*\n * Copyright 2023 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 Box from '@material-ui/core/Box';\nimport CircularProgress from '@material-ui/core/CircularProgress';\n\n/**\n * @internal\n */\nexport function TableLoadingBody(props: { colSpan?: number }) {\n return (\n <tbody data-testid=\"loading-indicator\">\n <tr>\n <td colSpan={props.colSpan}>\n <Box\n sx={{\n display: 'flex',\n justifyContent: 'center',\n alignItems: 'center',\n width: '100%',\n minHeight: '15rem',\n }}\n >\n <CircularProgress size=\"5rem\" />\n </Box>\n </td>\n </tr>\n </tbody>\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 {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport MTable, {\n Column,\n Icons,\n MaterialTableProps,\n MTableBody,\n MTableHeader,\n MTableToolbar,\n Options,\n} from '@material-table/core';\nimport Box from '@material-ui/core/Box';\nimport IconButton from '@material-ui/core/IconButton';\nimport {\n makeStyles,\n Theme,\n useTheme,\n withStyles,\n} from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport AddBox from '@material-ui/icons/AddBox';\nimport ArrowUpward from '@material-ui/icons/ArrowUpward';\nimport Check from '@material-ui/icons/Check';\nimport ChevronLeft from '@material-ui/icons/ChevronLeft';\nimport ChevronRight from '@material-ui/icons/ChevronRight';\nimport Clear from '@material-ui/icons/Clear';\nimport DeleteOutline from '@material-ui/icons/DeleteOutline';\nimport Edit from '@material-ui/icons/Edit';\nimport FilterList from '@material-ui/icons/FilterList';\nimport Search from '@material-ui/icons/Search';\nimport FirstPage from '@material-ui/icons/FirstPage';\nimport LastPage from '@material-ui/icons/LastPage';\nimport Remove from '@material-ui/icons/Remove';\nimport SaveAlt from '@material-ui/icons/SaveAlt';\nimport ViewColumn from '@material-ui/icons/ViewColumn';\nimport { isEqual, transform } from 'lodash';\nimport {\n CSSProperties,\n forwardRef,\n MutableRefObject,\n ReactNode,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react';\n\nimport { coreComponentsTranslationRef } from '../../translation';\nimport { SelectProps } from '../Select/Select';\nimport { Filter, Filters, SelectedFilters, Without } from './Filters';\nimport { TableLoadingBody } from './TableLoadingBody';\n\n// Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51\nconst tableIcons: Icons = {\n Add: forwardRef<SVGSVGElement>((props, ref) => (\n <AddBox {...props} ref={ref} />\n )),\n Check: forwardRef<SVGSVGElement>((props, ref) => (\n <Check {...props} ref={ref} />\n )),\n Clear: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Delete: forwardRef<SVGSVGElement>((props, ref) => (\n <DeleteOutline {...props} ref={ref} />\n )),\n DetailPanel: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n Edit: forwardRef<SVGSVGElement>((props, ref) => (\n <Edit {...props} ref={ref} />\n )),\n Export: forwardRef<SVGSVGElement>((props, ref) => (\n <SaveAlt {...props} ref={ref} />\n )),\n Filter: forwardRef<SVGSVGElement>((props, ref) => (\n <FilterList {...props} ref={ref} />\n )),\n FirstPage: forwardRef<SVGSVGElement>((props, ref) => (\n <FirstPage {...props} ref={ref} />\n )),\n LastPage: forwardRef<SVGSVGElement>((props, ref) => (\n <LastPage {...props} ref={ref} />\n )),\n NextPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronRight {...props} ref={ref} />\n )),\n PreviousPage: forwardRef<SVGSVGElement>((props, ref) => (\n <ChevronLeft {...props} ref={ref} />\n )),\n ResetSearch: forwardRef<SVGSVGElement>((props, ref) => (\n <Clear {...props} ref={ref} />\n )),\n Search: forwardRef<SVGSVGElement>((props, ref) => (\n <Search {...props} ref={ref} />\n )),\n SortArrow: forwardRef<SVGSVGElement>((props, ref) => (\n <ArrowUpward {...props} ref={ref} />\n )),\n ThirdStateCheck: forwardRef<SVGSVGElement>((props, ref) => (\n <Remove {...props} ref={ref} />\n )),\n ViewColumn: forwardRef<SVGSVGElement>((props, ref) => (\n <ViewColumn {...props} ref={ref} />\n )),\n};\n\n// TODO: Material table might already have such a function internally that we can use?\nfunction extractValueByField(data: any, field: string): any | undefined {\n const path = field.split('.');\n let value = data[path[0]];\n\n for (let i = 1; i < path.length; ++i) {\n if (value === undefined) {\n return value;\n }\n\n const f = path[i];\n value = value[f];\n }\n\n return value;\n}\n\nexport type TableHeaderClassKey = 'header';\n\nconst StyledMTableHeader = withStyles(\n theme => ({\n header: {\n padding: theme.spacing(1, 2, 1, 2.5),\n borderTop: `1px solid ${theme.palette.grey.A100}`,\n borderBottom: `1px solid ${theme.palette.grey.A100}`,\n // withStyles hasn't a generic overload for theme\n fontWeight: theme.typography.fontWeightBold,\n position: 'static',\n wordBreak: 'normal',\n textTransform: 'uppercase',\n },\n }),\n { name: 'BackstageTableHeader' },\n)(MTableHeader);\n\nexport type TableToolbarClassKey = 'root' | 'title' | 'searchField';\n\nconst StyledMTableToolbar = withStyles(\n theme => ({\n root: {\n padding: theme.spacing(3, 0, 2.5, 2.5),\n },\n title: {\n '& > h6': {\n fontWeight: theme.typography.fontWeightBold,\n },\n },\n searchField: {\n paddingRight: theme.spacing(2),\n },\n }),\n { name: 'BackstageTableToolbar' },\n)(MTableToolbar);\n\n/** @public */\nexport type FiltersContainerClassKey = 'root' | 'filterControls' | 'title';\n\nconst useFilterStyles = makeStyles(\n theme => ({\n root: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n flexWrap: 'wrap',\n },\n filterControls: {\n display: 'flex',\n alignItems: 'center',\n },\n title: {\n fontWeight: theme.typography.fontWeightBold,\n fontSize: 18,\n whiteSpace: 'nowrap',\n },\n }),\n { name: 'BackstageTableFiltersContainer' },\n);\n\nexport type TableClassKey = 'root';\n\nconst useTableStyles = makeStyles(\n () => ({\n root: {\n display: 'flex',\n alignItems: 'start',\n },\n }),\n { name: 'BackstageTable' },\n);\n\nfunction convertColumns<T extends object>(\n columns: TableColumn<T>[],\n theme: Theme,\n): TableColumn<T>[] {\n return columns.map(column => {\n const headerStyle: CSSProperties = column.headerStyle ?? {};\n\n let cellStyle = column.cellStyle || {};\n\n if (column.highlight) {\n headerStyle.color = theme.palette.textContrast;\n\n if (typeof cellStyle === 'object') {\n (cellStyle as CSSProperties).fontWeight =\n theme.typography.fontWeightBold;\n } else {\n const cellStyleFn = cellStyle as (\n data: any,\n rowData: T,\n column?: Column<T>,\n ) => CSSProperties;\n cellStyle = (data, rowData, rowColumn) => {\n const style = cellStyleFn(data, rowData, rowColumn);\n return { ...style, fontWeight: theme.typography.fontWeightBold };\n };\n }\n }\n\n return {\n ...column,\n headerStyle,\n cellStyle,\n };\n });\n}\n\nfunction removeDefaultValues(state: any, defaultState: any): any {\n return transform(state, (result, value, key) => {\n if (!isEqual(value, defaultState[key])) {\n result[key] = value;\n }\n });\n}\n\nconst defaultInitialState = {\n search: '',\n filtersOpen: false,\n filters: {},\n};\n\nexport interface TableColumn<T extends object = {}> extends Column<T> {\n highlight?: boolean;\n width?: string;\n}\n\nexport type TableFilter = {\n column: string;\n type: 'select' | 'multiple-select';\n};\n\nexport type TableState = {\n search?: string;\n filtersOpen?: boolean;\n filters?: SelectedFilters;\n};\n\nexport interface TableProps<T extends object = {}>\n extends MaterialTableProps<T> {\n columns: TableColumn<T>[];\n subtitle?: string;\n filters?: TableFilter[];\n initialState?: TableState;\n emptyContent?: ReactNode;\n isLoading?: boolean;\n onStateChange?: (state: TableState) => any;\n}\n\nexport interface TableOptions<T extends object = {}> extends Options<T> {}\n\nexport function TableToolbar(toolbarProps: {\n toolbarRef: MutableRefObject<any>;\n setSearch: (value: string) => void;\n onSearchChanged: (value: string) => void;\n toggleFilters: () => void;\n hasFilters: boolean;\n selectedFiltersLength: number;\n}) {\n const {\n toolbarRef,\n setSearch,\n hasFilters,\n selectedFiltersLength,\n toggleFilters,\n } = toolbarProps;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const filtersClasses = useFilterStyles();\n const onSearchChanged = useCallback(\n (searchText: string) => {\n toolbarProps.onSearchChanged(searchText);\n setSearch(searchText);\n },\n [toolbarProps, setSearch],\n );\n\n if (hasFilters) {\n return (\n <Box className={filtersClasses.root}>\n <Box className={filtersClasses.filterControls}>\n <IconButton onClick={toggleFilters} aria-label=\"filter list\">\n <FilterList />\n </IconButton>\n <Typography className={filtersClasses.title}>\n {t('table.filter.title')} ({selectedFiltersLength})\n </Typography>\n </Box>\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n </Box>\n );\n }\n\n return (\n <StyledMTableToolbar\n {...toolbarProps}\n ref={toolbarRef}\n onSearchChanged={onSearchChanged}\n />\n );\n}\n\n/**\n * @public\n */\nexport function Table<T extends object = {}>(props: TableProps<T>) {\n const {\n data,\n columns,\n emptyContent,\n options,\n title,\n subtitle,\n localization,\n filters,\n initialState,\n onStateChange,\n components,\n isLoading: loading,\n style,\n ...restProps\n } = props;\n const { t } = useTranslationRef(coreComponentsTranslationRef);\n const tableClasses = useTableStyles();\n\n const theme = useTheme();\n\n const calculatedInitialState = { ...defaultInitialState, ...initialState };\n\n const [filtersOpen, setFiltersOpen] = useState(\n calculatedInitialState.filtersOpen,\n );\n const toggleFilters = useCallback(\n () => setFiltersOpen(v => !v),\n [setFiltersOpen],\n );\n\n const [selectedFilters, setSelectedFilters] = useState(\n calculatedInitialState.filters,\n );\n\n const [search, setSearch] = useState(calculatedInitialState.search);\n\n useEffect(() => {\n if (onStateChange) {\n const state = removeDefaultValues(\n {\n search,\n filtersOpen,\n filters: selectedFilters,\n },\n defaultInitialState,\n );\n\n onStateChange(state);\n }\n }, [search, filtersOpen, selectedFilters, onStateChange]);\n\n const getFieldByTitle = useCallback(\n (titleValue: string | keyof T) =>\n columns.find(el => el.title === titleValue)?.field,\n [columns],\n );\n\n const tableData = useMemo(() => {\n if (typeof data === 'function' || !selectedFilters) {\n return data;\n }\n\n const selectedFiltersArray = Object.values(selectedFilters);\n if (data && selectedFiltersArray.flat().length) {\n const newData = (data as any[]).filter(\n el =>\n !!Object.entries(selectedFilters)\n .filter(([, value]) => !!(value as { length?: number }).length)\n .every(([key, filterValue]) => {\n const fieldValue = extractValueByField(\n el,\n getFieldByTitle(key) as string,\n );\n\n if (Array.isArray(fieldValue) && Array.isArray(filterValue)) {\n return fieldValue.some(v => filterValue.includes(v));\n } else if (Array.isArray(fieldValue)) {\n return fieldValue.includes(filterValue);\n } else if (Array.isArray(filterValue)) {\n return filterValue.includes(fieldValue);\n }\n\n return fieldValue === filterValue;\n }),\n );\n return newData;\n }\n return data;\n }, [data, selectedFilters, getFieldByTitle]);\n\n const selectedFiltersLength = Object.values(selectedFilters).flat().length;\n\n const hasFilters = !!filters?.length;\n const Toolbar = useCallback(\n (toolbarProps: any /* no type for this in material-table */) => {\n return (\n <TableToolbar\n setSearch={setSearch}\n hasFilters={hasFilters}\n selectedFiltersLength={selectedFiltersLength}\n toggleFilters={toggleFilters}\n {...toolbarProps}\n />\n );\n },\n [toggleFilters, hasFilters, selectedFiltersLength, setSearch],\n );\n\n const hasNoRows = typeof data !== 'function' && data.length === 0;\n const columnCount = columns.length;\n const Body = useMemo(\n () => makeBody({ hasNoRows, emptyContent, columnCount, loading }),\n [hasNoRows, emptyContent, columnCount, loading],\n );\n\n return (\n <Box className={tableClasses.root}>\n {filtersOpen && data && typeof data !== 'function' && filters?.length && (\n <Filters\n filters={constructFilters(filters, data as any[], columns, t)}\n selectedFilters={selectedFilters}\n onChangeFilters={setSelectedFilters}\n />\n )}\n <MTable<T>\n components={{\n Header: StyledMTableHeader,\n Body,\n Toolbar,\n ...components,\n }}\n options={options}\n columns={convertColumns(columns, theme)}\n icons={tableIcons}\n title={\n <>\n <Typography variant=\"h5\" component=\"h2\">\n {title}\n </Typography>\n {subtitle && (\n <Typography color=\"textSecondary\" variant=\"body1\">\n {subtitle}\n </Typography>\n )}\n </>\n }\n data={tableData}\n style={{ width: '100%', ...style }}\n localization={{\n ...localization,\n body: {\n emptyDataSourceMessage: t('table.body.emptyDataSourceMessage'),\n ...localization?.body,\n },\n pagination: {\n firstTooltip: t('table.pagination.firstTooltip'),\n labelDisplayedRows: t('table.pagination.labelDisplayedRows'),\n labelRowsSelect: t('table.pagination.labelRowsSelect'),\n lastTooltip: t('table.pagination.lastTooltip'),\n nextTooltip: t('table.pagination.nextTooltip'),\n previousTooltip: t('table.pagination.previousTooltip'),\n ...localization?.pagination,\n },\n header: {\n actions: t('table.header.actions'),\n ...localization?.header,\n },\n toolbar: {\n searchPlaceholder: t('table.toolbar.search'),\n searchTooltip: t('table.toolbar.search'),\n ...localization?.toolbar,\n },\n }}\n {...restProps}\n />\n </Box>\n );\n}\n\nTable.icons = Object.freeze(tableIcons);\n\nfunction makeBody({\n columnCount,\n emptyContent,\n hasNoRows,\n loading,\n}: {\n hasNoRows: boolean;\n emptyContent: ReactNode;\n columnCount: number;\n loading?: boolean;\n}) {\n return (bodyProps: any /* no type for this in material-table */) => {\n if (loading) {\n return <TableLoadingBody colSpan={columnCount} />;\n }\n\n if (emptyContent && hasNoRows) {\n return (\n <tbody>\n <tr>\n <td colSpan={columnCount}>{emptyContent}</td>\n </tr>\n </tbody>\n );\n }\n\n return <MTableBody {...bodyProps} />;\n };\n}\n\nfunction constructFilters<T extends object>(\n filterConfig: TableFilter[],\n dataValue: any[] | undefined,\n columns: TableColumn<T>[],\n t: TranslationFunction<typeof coreComponentsTranslationRef.T>,\n): Filter[] {\n const extractDistinctValues = (field: string | keyof T): Set<any> => {\n const distinctValues = new Set<any>();\n const addValue = (value: any) => {\n if (value !== undefined && value !== null) {\n distinctValues.add(value);\n }\n };\n\n if (dataValue) {\n dataValue.forEach(el => {\n const value = extractValueByField(\n el,\n columns.find(c => c.title === field)?.field as string,\n );\n\n if (Array.isArray(value)) {\n (value as []).forEach(addValue);\n } else {\n addValue(value);\n }\n });\n }\n\n return distinctValues;\n };\n\n const constructSelect = (\n filter: TableFilter,\n ): Without<SelectProps, 'onChange'> => {\n return {\n placeholder: t('table.filter.placeholder'),\n label: filter.column,\n multiple: filter.type === 'multiple-select',\n items: [...extractDistinctValues(filter.column)].sort().map(value => ({\n label: value,\n value,\n })),\n };\n };\n\n return filterConfig.map(filter => ({\n type: filter.type,\n element: constructSelect(filter),\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 Grid from '@material-ui/core/Grid';\nimport { alpha, makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { ReactNode, PropsWithChildren } from 'react';\nimport { Link } from '../../components/Link';\n\n/** @public */\nexport type HeaderLabelClassKey = 'root' | 'label' | 'value';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n textAlign: 'left',\n },\n label: {\n color: theme.page.fontColor,\n fontWeight: theme.typography.fontWeightBold,\n letterSpacing: 0,\n fontSize: theme.typography.fontSize,\n marginBottom: theme.spacing(1) / 2,\n lineHeight: 1,\n },\n value: {\n color: alpha(theme.page.fontColor, 0.8),\n fontSize: theme.typography.fontSize,\n lineHeight: 1,\n },\n }),\n { name: 'BackstageHeaderLabel' },\n);\n\ntype HeaderLabelContentProps = PropsWithChildren<{\n value: ReactNode;\n className: string;\n typographyRootComponent?: keyof JSX.IntrinsicElements;\n}>;\n\nconst HeaderLabelContent = ({\n value,\n className,\n typographyRootComponent,\n}: HeaderLabelContentProps) => {\n return (\n <Typography\n component={\n typographyRootComponent ?? (typeof value === 'string' ? 'p' : 'span')\n }\n className={className}\n >\n {value}\n </Typography>\n );\n};\n\ntype HeaderLabelProps = {\n label: string;\n value?: HeaderLabelContentProps['value'];\n contentTypograpyRootComponent?: HeaderLabelContentProps['typographyRootComponent'];\n url?: string;\n};\n\n/**\n * Additional label to main {@link Header}\n *\n * @public\n *\n */\nexport function HeaderLabel(props: HeaderLabelProps) {\n const { label, value, url, contentTypograpyRootComponent } = props;\n const classes = useStyles();\n const content = (\n <HeaderLabelContent\n className={classes.value}\n value={value || '<Unknown>'}\n typographyRootComponent={contentTypograpyRootComponent}\n />\n );\n return (\n <Grid item>\n <Typography component=\"span\" className={classes.root}>\n <Typography className={classes.label}>{label}</Typography>\n {url ? <Link to={url}>{content}</Link> : content}\n </Typography>\n </Grid>\n );\n}\n","/*\n * Copyright 2026 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 CompoundEntityRef,\n Entity,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n EntityPresentationApi,\n EntityRefPresentationSnapshot,\n} from './EntityPresentationApi';\nimport { defaultEntityPresentation } from './defaultEntityPresentation';\n\n/**\n * Returns a synchronous presentation snapshot for an entity in non-React\n * contexts.\n *\n * @remarks\n *\n * This is the synchronous, non-React counterpart to\n * {@link useEntityPresentation}. It handles `Entity`, `CompoundEntityRef`,\n * and string ref inputs uniformly, using the provided\n * {@link EntityPresentationApi} when available and falling back to\n * {@link defaultEntityPresentation} otherwise.\n *\n * Because this function is synchronous, it uses cached data from the\n * presentation API (via `.snapshot`). If the entity has been seen before,\n * the snapshot will contain the full resolved title; otherwise it falls\n * back to what can be extracted from the ref alone. This is the correct\n * trade-off for sort comparators, column factories, filter callbacks, and\n * data mappers where a synchronous return value is required.\n *\n * In async contexts such as data loaders where you can `await`, prefer\n * using the {@link EntityPresentationApi} directly via\n * `forEntity().promise` for the richest possible presentation.\n *\n * @public\n * @param entityOrRef - An entity, a compound entity ref, or a string entity ref.\n * @param context - Optional context that may affect the presentation.\n * @param entityPresentationApi - Optional presentation API instance. When not\n * provided, falls back to {@link defaultEntityPresentation}.\n */\nexport function entityPresentationSnapshot(\n entityOrRef: Entity | CompoundEntityRef | string,\n context?: { defaultKind?: string; defaultNamespace?: string },\n entityPresentationApi?: EntityPresentationApi,\n): EntityRefPresentationSnapshot {\n if (entityPresentationApi) {\n const ref =\n typeof entityOrRef === 'string' || 'metadata' in entityOrRef\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n return entityPresentationApi.forEntity(ref, context).snapshot;\n }\n return defaultEntityPresentation(entityOrRef, context);\n}\n","/*\n * Copyright 2024 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 Box from '@material-ui/core/Box';\nimport Typography, { TypographyProps } from '@material-ui/core/Typography';\nimport Paper, { PaperProps } from '@material-ui/core/Paper';\nimport Popper, { PopperProps } from '@material-ui/core/Popper';\nimport TextField, { OutlinedTextFieldProps } from '@material-ui/core/TextField';\nimport Grow from '@material-ui/core/Grow';\nimport {\n createStyles,\n makeStyles,\n Theme,\n withStyles,\n} from '@material-ui/core/styles';\nimport ExpandMoreIcon from '@material-ui/icons/ExpandMore';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport { ReactNode, useCallback } from 'react';\nimport { merge } from 'lodash';\nimport classNames from 'classnames';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n margin: theme.spacing(1, 0),\n },\n label: {\n position: 'relative',\n fontWeight: 'bold',\n fontSize: theme.typography.body2.fontSize,\n fontFamily: theme.typography.fontFamily,\n color: theme.palette.text.primary,\n '& > span': {\n top: 0,\n left: 0,\n position: 'absolute',\n },\n },\n }),\n { name: 'BackstageAutocomplete' },\n);\n\nconst BootstrapAutocomplete = withStyles(\n (theme: Theme) =>\n createStyles({\n root: {},\n paper: {\n margin: 0,\n },\n hasClearIcon: {},\n hasPopupIcon: {},\n focused: {},\n inputRoot: {\n marginTop: 24,\n backgroundColor: theme.palette.background.paper,\n '$root$hasClearIcon$hasPopupIcon &': {\n paddingBlock: theme.spacing(0.75),\n paddingInlineStart: theme.spacing(0.75),\n },\n '$root$focused &': {\n outline: 'none',\n },\n '$root &:hover > fieldset': {\n borderColor: '#ced4da',\n },\n '$root$focused & > fieldset': {\n borderWidth: 1,\n borderColor: theme.palette.primary.main,\n },\n },\n popupIndicator: {\n padding: 0,\n margin: 0,\n color: '#616161',\n '&:hover': {\n backgroundColor: 'unset',\n },\n '& [class*=\"MuiTouchRipple-root\"]': {\n display: 'none',\n },\n },\n endAdornment: {\n '$root$hasClearIcon$hasPopupIcon &': {\n right: 4,\n },\n },\n input: {\n '$root$hasClearIcon$hasPopupIcon &': {\n fontSize: theme.typography.body1.fontSize,\n paddingBlock: theme.spacing(0.8125),\n },\n },\n }),\n { name: 'BackstageAutocompleteBase' },\n)(Autocomplete) as typeof Autocomplete;\n\nconst PopperComponent = (props: PopperProps) => (\n <Popper {...props} transition placement=\"bottom-start\">\n {({ TransitionProps }) => (\n <Grow {...TransitionProps} style={{ transformOrigin: '0 0 0' }}>\n <Box>{props.children as ReactNode}</Box>\n </Grow>\n )}\n </Popper>\n);\n\nconst PaperComponent = (props: PaperProps) => (\n <Paper {...props} elevation={8} />\n);\n\n/**\n * Props for {@link CatalogAutocomplete}\n *\n * @public\n */\nexport type CatalogAutocompleteProps<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n> = Omit<\n AutocompleteProps<T, Multiple, DisableClearable, FreeSolo>,\n 'PopperComponent' | 'PaperComponent' | 'popupIcon' | 'renderInput'\n> & {\n name: string;\n label?: string;\n LabelProps?: TypographyProps<'label'>;\n TextFieldProps?: Omit<OutlinedTextFieldProps, 'variant'>;\n renderInput?: AutocompleteProps<\n T,\n Multiple,\n DisableClearable,\n FreeSolo\n >['renderInput'];\n};\n\n/** @public */\nexport function CatalogAutocomplete<\n T,\n Multiple extends boolean | undefined = undefined,\n DisableClearable extends boolean | undefined = undefined,\n FreeSolo extends boolean | undefined = undefined,\n>(props: CatalogAutocompleteProps<T, Multiple, DisableClearable, FreeSolo>) {\n const { label, name, LabelProps, TextFieldProps, ...rest } = props;\n const classes = useStyles();\n const renderInput = useCallback(\n (params: AutocompleteRenderInputParams) => (\n <TextField {...merge(params, TextFieldProps)} variant=\"outlined\" />\n ),\n [TextFieldProps],\n );\n const autocomplete = (\n <BootstrapAutocomplete\n size=\"small\"\n {...rest}\n renderInput={rest.renderInput ?? renderInput}\n popupIcon={<ExpandMoreIcon data-testid={`${name}-expand`} />}\n PaperComponent={PaperComponent}\n PopperComponent={PopperComponent}\n />\n );\n\n return (\n <Box className={classes.root}>\n {label ? (\n <Typography\n {...LabelProps}\n className={classNames(classes.label, LabelProps?.className)}\n component=\"label\"\n >\n <Box component=\"span\">{label}</Box>\n {autocomplete}\n </Typography>\n ) : (\n autocomplete\n )}\n </Box>\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 { ReactNode, useState } from 'react';\nimport Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport Drawer from '@material-ui/core/Drawer';\nimport Grid from '@material-ui/core/Grid';\nimport Typography from '@material-ui/core/Typography';\nimport useMediaQuery from '@material-ui/core/useMediaQuery';\nimport { Theme, useTheme } from '@material-ui/core/styles';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport const Filters = (props: {\n children: ReactNode;\n options?: {\n drawerBreakpoint?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | number;\n drawerAnchor?: 'left' | 'right' | 'top' | 'bottom';\n };\n}) => {\n const isScreenSmallerThanBreakpoint = useMediaQuery(\n (theme: Theme) =>\n theme.breakpoints.down(props.options?.drawerBreakpoint ?? 'md'),\n { noSsr: true },\n );\n const theme = useTheme();\n const [filterDrawerOpen, setFilterDrawerOpen] = useState<boolean>(false);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return isScreenSmallerThanBreakpoint ? (\n <>\n <Button\n style={{ marginTop: theme.spacing(1), marginLeft: theme.spacing(1) }}\n onClick={() => setFilterDrawerOpen(true)}\n startIcon={<FilterListIcon />}\n >\n {t('catalogFilter.buttonTitle')}\n </Button>\n <Drawer\n open={filterDrawerOpen}\n onClose={() => setFilterDrawerOpen(false)}\n anchor={props.options?.drawerAnchor ?? 'left'}\n disableAutoFocus\n keepMounted\n variant=\"temporary\"\n >\n <Box m={2}>\n <Typography\n variant=\"h6\"\n component=\"h2\"\n style={{ marginBottom: theme.spacing(1) }}\n >\n {t('catalogFilter.title')}\n </Typography>\n {props.children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const Content = (props: { children: ReactNode }) => {\n return (\n <Grid item xs={12} lg={10}>\n {props.children}\n </Grid>\n );\n};\n\n/** @public */\nexport const CatalogFilterLayout = (props: { children: ReactNode }) => {\n return (\n <Grid container style={{ position: 'relative' }}>\n {props.children}\n </Grid>\n );\n};\n\nCatalogFilterLayout.Filters = Filters;\nCatalogFilterLayout.Content = Content;\n","/*\n * Copyright 2022 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 Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { memo } from 'react';\n\ninterface Props {\n selected: boolean;\n value: string;\n availableOptions?: Record<string, number>;\n showCounts: boolean;\n}\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\nfunction OptionCheckbox({ selected }: { selected: boolean }) {\n return <Checkbox icon={icon} checkedIcon={checkedIcon} checked={selected} />;\n}\n\nexport const EntityAutocompletePickerOption = memo((props: Props) => {\n const { selected, value, availableOptions, showCounts } = props;\n const label = showCounts ? `${value} (${availableOptions?.[value]})` : value;\n\n return (\n <FormControlLabel\n control={<OptionCheckbox selected={selected} />}\n label={label}\n onClick={event => event.preventDefault()}\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 Box from '@material-ui/core/Box';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { useEffect, useMemo, useState } from 'react';\nimport { useApi } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityAutocompletePickerOption } from './EntityAutocompletePickerOption';\nimport {\n DefaultEntityFilters,\n useEntityList,\n} from '../../hooks/useEntityListProvider';\nimport { EntityFilter } from '../../types';\nimport { reduceBackendCatalogFilters } from '../../utils/filters';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\nimport { isEqual } from 'lodash';\n\n/** @public */\nexport type AllowedEntityFilters<T extends DefaultEntityFilters> = {\n [K in keyof T]-?: NonNullable<T[K]> extends EntityFilter & {\n values: string[];\n }\n ? K\n : never;\n}[keyof T];\n\n/** @public */\nexport type EntityAutocompletePickerProps<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n> = {\n label: string;\n name: Name;\n path: string;\n showCounts?: boolean;\n Filter: { new (values: string[]): NonNullable<T[Name]> };\n InputProps?: TextFieldProps;\n initialSelectedOptions?: string[];\n filtersForAvailableValues?: Array<keyof T>;\n hidden?: boolean;\n};\n\n/** @public */\nexport type CatalogReactEntityAutocompletePickerClassKey = 'root' | 'label';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {\n textTransform: 'none',\n fontWeight: 'bold',\n },\n },\n { name: 'CatalogReactEntityAutocompletePicker' },\n);\n\n/** @public */\nexport function EntityAutocompletePicker<\n T extends DefaultEntityFilters = DefaultEntityFilters,\n Name extends AllowedEntityFilters<T> = AllowedEntityFilters<T>,\n>(props: EntityAutocompletePickerProps<T, Name>) {\n const {\n label,\n name,\n path,\n showCounts,\n Filter,\n InputProps,\n initialSelectedOptions = [],\n filtersForAvailableValues = ['kind'],\n hidden,\n } = props;\n const classes = useStyles();\n\n const {\n updateFilters,\n filters,\n queryParameters: { [name]: queryParameter },\n } = useEntityList<T>();\n\n const catalogApi = useApi(catalogApiRef);\n const availableValuesFilters = filtersForAvailableValues.map(\n f => filters[f] as EntityFilter | undefined,\n );\n const { value: availableValues } = useAsync(async () => {\n const facet = path;\n const { facets } = await catalogApi.getEntityFacets({\n facets: [facet],\n filter: reduceBackendCatalogFilters(\n availableValuesFilters.filter(Boolean) as EntityFilter[],\n ),\n });\n\n return Object.fromEntries(\n facets[facet].map(({ value, count }) => [value, count]),\n );\n }, [...availableValuesFilters]);\n\n const queryParameters = useMemo(\n () => [queryParameter].flat().filter(Boolean) as string[],\n [queryParameter],\n );\n\n const filteredOptions = (filters[name] as unknown as { values: string[] })\n ?.values;\n\n const [selectedOptions, setSelectedOptions] = useState(\n queryParameters.length\n ? queryParameters\n : filteredOptions ?? initialSelectedOptions,\n );\n\n // Set selected options on query parameter updates; this happens at initial page load and from\n // external updates to the page location\n useEffect(() => {\n if (queryParameters.length) {\n setSelectedOptions(queryParameters);\n }\n }, [queryParameters]);\n\n const availableOptions = Object.keys(availableValues ?? {});\n const shouldAddFilter = selectedOptions.length && availableOptions.length;\n\n // Update filter value when selectedOptions change\n useEffect(() => {\n updateFilters({\n [name]: shouldAddFilter ? new Filter(selectedOptions) : undefined,\n } as Partial<T>);\n }, [name, shouldAddFilter, selectedOptions, Filter, updateFilters]);\n\n // Update selected options when filter value changes\n useEffect(() => {\n if (!shouldAddFilter) return;\n\n const newSelectedOptions = filteredOptions ?? [];\n\n // Check value is actually different (not just a different reference) to prevent selectedOptions <> filters loop\n if (!isEqual(newSelectedOptions, selectedOptions)) {\n setSelectedOptions(newSelectedOptions);\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps -- Don't re-set filter value when selectedOptions changes\n }, [filteredOptions]);\n\n const filter = filters[name];\n if (\n (filter && typeof filter === 'object' && !('values' in filter)) ||\n !availableOptions.length\n ) {\n return null;\n }\n\n return hidden ? null : (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<string, true>\n multiple\n disableCloseOnSelect\n label={label}\n name={`${String(name)}-picker`}\n options={availableOptions}\n value={selectedOptions}\n TextFieldProps={InputProps}\n onChange={(_event: object, options: string[]) =>\n setSelectedOptions(options)\n }\n renderOption={(option, { selected }) => (\n <EntityAutocompletePickerOption\n selected={selected}\n value={option}\n availableOptions={availableValues}\n showCounts={!!showCounts}\n />\n )}\n />\n </Box>\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 {\n Entity,\n parseEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport Box from '@material-ui/core/Box';\nimport Checkbox from '@material-ui/core/Checkbox';\nimport FormControlLabel from '@material-ui/core/FormControlLabel';\nimport Typography from '@material-ui/core/Typography';\nimport Tooltip from '@material-ui/core/Tooltip';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CheckBoxIcon from '@material-ui/icons/CheckBox';\nimport CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';\nimport { MouseEvent, useEffect, useMemo, useState } from 'react';\nimport { useEntityList } from '../../hooks/useEntityListProvider';\nimport { EntityOwnerFilter } from '../../filters';\nimport { useDebouncedEffect } from '@react-hookz/web';\nimport PersonIcon from '@material-ui/icons/Person';\nimport GroupIcon from '@material-ui/icons/Group';\nimport {\n entityPresentationApiRef,\n entityPresentationSnapshot,\n} from '../../apis';\nimport { useFetchEntities } from './useFetchEntities';\nimport { withStyles } from '@material-ui/core/styles';\nimport { useEntityPresentation } from '../../apis';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useApiHolder } from '@backstage/core-plugin-api';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\nimport { CatalogAutocomplete } from '../CatalogAutocomplete';\n\n/** @public */\nexport type CatalogReactEntityOwnerPickerClassKey = 'input';\n\nconst useStyles = makeStyles(\n {\n root: {},\n label: {},\n input: {},\n fullWidth: { width: '100%' },\n boxLabel: {\n width: '100%',\n textOverflow: 'ellipsis',\n overflow: 'hidden',\n },\n },\n { name: 'CatalogReactEntityOwnerPicker' },\n);\n\n/** @public */\nexport type FixedWidthFormControlLabelClassKey = 'label' | 'root';\n\nconst FixedWidthFormControlLabel = withStyles(\n _theme => ({\n label: {\n width: '100%',\n },\n root: {\n width: '90%',\n },\n }),\n { name: 'FixedWidthFormControlLabel' },\n)(FormControlLabel);\n\nconst icon = <CheckBoxOutlineBlankIcon fontSize=\"small\" />;\nconst checkedIcon = <CheckBoxIcon fontSize=\"small\" />;\n\n/**\n * @public\n */\nexport type EntityOwnerPickerProps = {\n mode?: 'owners-only' | 'all';\n};\n\nfunction RenderOptionLabel(props: { entity: Entity; isSelected: boolean }) {\n const classes = useStyles();\n const isGroup = props.entity.kind.toLocaleLowerCase('en-US') === 'group';\n const { primaryTitle: title } = useEntityPresentation(props.entity);\n return (\n <Box className={classes.fullWidth}>\n <FixedWidthFormControlLabel\n className={classes.fullWidth}\n control={\n <Checkbox\n icon={icon}\n checkedIcon={checkedIcon}\n checked={props.isSelected}\n />\n }\n onClick={event => event.preventDefault()}\n label={\n <Tooltip title={title}>\n <Box display=\"flex\" alignItems=\"center\">\n {isGroup ? (\n <GroupIcon fontSize=\"small\" />\n ) : (\n <PersonIcon fontSize=\"small\" />\n )}\n &nbsp;\n <Box className={classes.boxLabel}>\n <Typography noWrap>{title}</Typography>\n </Box>\n </Box>\n </Tooltip>\n }\n />\n </Box>\n );\n}\n\n/** @public */\nexport const EntityOwnerPicker = (props?: EntityOwnerPickerProps) => {\n const classes = useStyles();\n const { mode = 'owners-only' } = props || {};\n const apis = useApiHolder();\n const entityPresentationApi = apis.get(entityPresentationApiRef);\n const {\n updateFilters,\n filters,\n queryParameters: { owners: ownersParameter },\n } = useEntityList();\n\n const [text, setText] = useState('');\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n const queryParamOwners = useMemo(\n () => [ownersParameter].flat().filter(Boolean) as string[],\n [ownersParameter],\n );\n\n const [selectedOwners, setSelectedOwners] = useState<string[]>(\n queryParamOwners.length ? queryParamOwners : filters.owners?.values ?? [],\n );\n\n const [{ value, loading }, handleFetch, cache] = useFetchEntities({\n mode,\n initialSelectedOwnersRefs: selectedOwners,\n });\n useDebouncedEffect(\n () => handleFetch({ text: text.toLocaleLowerCase('en-US') }),\n [text, handleFetch],\n 250,\n );\n\n const availableOwners = value?.items || [];\n\n // Set selected owners on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamOwners.length) {\n const filter = new EntityOwnerFilter(queryParamOwners);\n setSelectedOwners(filter.values);\n }\n }, [queryParamOwners]);\n\n useEffect(() => {\n updateFilters({\n owners: selectedOwners.length\n ? new EntityOwnerFilter(selectedOwners)\n : undefined,\n });\n }, [selectedOwners, updateFilters]);\n\n if (\n ['user', 'group'].includes(\n filters.kind?.value.toLocaleLowerCase('en-US') || '',\n )\n ) {\n return null;\n }\n\n return (\n <Box className={classes.root} pb={1} pt={1}>\n <CatalogAutocomplete<Entity, true>\n label={t('entityOwnerPicker.title')}\n multiple\n disableCloseOnSelect\n loading={loading}\n options={availableOwners}\n value={selectedOwners as unknown as Entity[]}\n getOptionSelected={(o, v) => {\n if (typeof v === 'string') {\n return stringifyEntityRef(o) === v;\n }\n return o === v;\n }}\n getOptionLabel={o => {\n const entity =\n typeof o === 'string'\n ? cache.getEntity(o) ||\n parseEntityRef(o, {\n defaultKind: 'group',\n defaultNamespace: 'default',\n })\n : o;\n return entityPresentationSnapshot(\n entity,\n undefined,\n entityPresentationApi,\n ).primaryTitle;\n }}\n onChange={(_: object, owners) => {\n setText('');\n setSelectedOwners(\n owners.map(e => {\n const entityRef =\n typeof e === 'string' ? e : stringifyEntityRef(e);\n\n if (typeof e !== 'string') {\n cache.setEntity(e);\n }\n return entityRef;\n }),\n );\n }}\n filterOptions={x => x}\n renderOption={(entity, { selected }) => {\n return <RenderOptionLabel entity={entity} isSelected={selected} />;\n }}\n name=\"owner-picker\"\n onInputChange={(_e, inputValue) => {\n setText(inputValue);\n }}\n ListboxProps={{\n onScroll: (e: MouseEvent) => {\n const element = e.currentTarget;\n const hasReachedEnd =\n Math.abs(\n element.scrollHeight - element.clientHeight - element.scrollTop,\n ) < 1;\n\n if (hasReachedEnd && value?.cursor) {\n handleFetch({ items: value.items, cursor: value.cursor });\n }\n },\n 'data-testid': 'owner-picker-listbox',\n }}\n LabelProps={{ className: classes.label }}\n TextFieldProps={{ className: classes.input }}\n />\n </Box>\n );\n};\n","/*\n * Copyright 2023 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 { useRef } from 'react';\nimport { useFacetsEntities } from './useFacetsEntities';\nimport { useQueryEntities } from './useQueryEntities';\nimport { Entity, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { useMountEffect } from '@react-hookz/web';\n\nexport function useFetchEntities({\n mode,\n initialSelectedOwnersRefs,\n}: {\n mode: 'owners-only' | 'all';\n initialSelectedOwnersRefs: string[];\n}) {\n const isOwnersOnlyMode = mode === 'owners-only';\n const queryEntitiesResponse = useQueryEntities();\n const facetsEntitiesResponse = useFacetsEntities({\n enabled: isOwnersOnlyMode,\n });\n\n const [state, handleFetch] = isOwnersOnlyMode\n ? facetsEntitiesResponse\n : queryEntitiesResponse;\n\n return [\n state,\n handleFetch,\n useSelectedOwners({\n enabled: !isOwnersOnlyMode,\n initialSelectedOwnersRefs,\n }),\n ] as const;\n}\n\n/**\n * Hook used for storing the full entity of the specified owners\n * in order to display users and group using the information contained on each entity.\n * When a component is rendered for the first time, it loads the content of the entities\n * specified by `initialSelectedOwnersRefs` and export the `getEntity` and `setEntity`\n * utilities, used to retrieve and modify the owners.\n */\nfunction useSelectedOwners({\n enabled,\n initialSelectedOwnersRefs,\n}: {\n enabled: boolean;\n initialSelectedOwnersRefs: string[];\n}) {\n const allEntities = useRef<Record<string, Entity>>({});\n const catalogApi = useApi(catalogApiRef);\n\n const [, handleFetch] = useAsyncFn(async () => {\n const initialSelectedEntities = await catalogApi.getEntitiesByRefs({\n entityRefs: initialSelectedOwnersRefs,\n });\n initialSelectedEntities.items.forEach(e => {\n if (e) {\n allEntities.current[stringifyEntityRef(e)] = e;\n }\n });\n }, []);\n\n useMountEffect(() => {\n if (enabled && initialSelectedOwnersRefs.length > 0) {\n handleFetch();\n }\n });\n\n return {\n getEntity: (entityRef: string) => allEntities.current[entityRef],\n setEntity: (entity: Entity) => {\n allEntities.current[stringifyEntityRef(entity)] = entity;\n },\n };\n}\n","/*\n * Copyright 2023 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 { useApi } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '../../api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { Entity } from '@backstage/catalog-model';\n\ntype QueryEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\nexport function useQueryEntities() {\n const catalogApi = useApi(catalogApiRef);\n return useAsyncFn(\n async (\n request: { text: string } | QueryEntitiesResponse,\n options?: { limit: number },\n ): Promise<QueryEntitiesResponse> => {\n const initialRequest = request as { text: string };\n const cursorRequest = request as QueryEntitiesResponse;\n const limit = options?.limit ?? 20;\n\n if (cursorRequest.cursor) {\n const response = await catalogApi.queryEntities({\n cursor: cursorRequest.cursor,\n limit,\n });\n return {\n cursor: response.pageInfo.nextCursor,\n items: [...cursorRequest.items, ...response.items],\n };\n }\n\n const response = await catalogApi.queryEntities({\n fullTextFilter: {\n term: initialRequest.text || '',\n fields: [\n 'metadata.name',\n 'kind',\n 'spec.profile.displayname',\n 'metadata.title',\n ],\n },\n filter: { kind: ['User', 'Group'] },\n orderFields: [{ field: 'metadata.name', order: 'asc' }],\n limit,\n });\n\n return {\n cursor: response.pageInfo.nextCursor,\n items: response.items,\n };\n },\n [],\n { loading: true },\n );\n}\n","/*\n * Copyright 2023 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 { useApi } from '@backstage/core-plugin-api';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport { catalogApiRef } from '../../api';\nimport { useState } from 'react';\nimport { Entity, parseEntityRef } from '@backstage/catalog-model';\n\ntype FacetsCursor = {\n start: number;\n text: string;\n};\n\ntype FacetsEntitiesResponse = {\n items: Entity[];\n cursor?: string;\n};\n\ntype FacetsInitialRequest = {\n text: string;\n};\n\n/**\n * This hook asynchronously loads the entity owners using the facets endpoint.\n * EntityOwnerPicker uses this hook when mode=\"owners-only\" is passed as prop.\n * All the owners are kept internally in memory and rendered in batches once requested\n * by the frontend. The values returned by this hook are compatible with `useQueryEntities`\n * hook, which is also used by EntityOwnerPicker.\n * In this mode, the EntityOwnerPicker won't show detailed information of the owners.\n */\nexport function useFacetsEntities({ enabled }: { enabled: boolean }) {\n const catalogApi = useApi(catalogApiRef);\n\n const [facetsPromise] = useState(async () => {\n if (!enabled) {\n return [];\n }\n const facet = 'relations.ownedBy';\n\n return catalogApi\n .getEntityFacets({ facets: [facet] })\n .then(response =>\n response.facets[facet]\n .map(e => e.value)\n .map(ref => {\n const { kind, name, namespace } = parseEntityRef(ref);\n return {\n apiVersion: 'backstage.io/v1beta1',\n kind,\n metadata: { name, namespace },\n };\n })\n .sort(\n (a, b) =>\n a.kind.localeCompare(b.kind, 'en-US') ||\n a.metadata.namespace.localeCompare(\n b.metadata.namespace,\n 'en-US',\n ) ||\n a.metadata.name.localeCompare(b.metadata.name, 'en-US'),\n ),\n )\n .catch(() => []);\n });\n\n return useAsyncFn<\n (\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n options?: { limit?: number },\n ) => Promise<FacetsEntitiesResponse>\n >(\n async (request, options) => {\n const facets = await facetsPromise;\n\n if (!facets) {\n return {\n items: [],\n };\n }\n\n const limit = options?.limit ?? 20;\n\n const { text, start } = decodeCursor(request);\n const filteredRefs = facets.filter(e => filterEntity(text, e));\n const end = start + limit;\n return {\n items: filteredRefs.slice(0, end),\n ...encodeCursor({\n entities: filteredRefs,\n limit: end,\n payload: {\n text,\n start: end,\n },\n }),\n };\n },\n [facetsPromise],\n { loading: true, value: { items: [] } },\n );\n}\n\nfunction decodeCursor(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): FacetsCursor {\n if (isFacetsResponse(request) && request.cursor) {\n return JSON.parse(atob(request.cursor));\n }\n return {\n text: (request as FacetsInitialRequest).text || '',\n start: 0,\n };\n}\n\nfunction isFacetsResponse(\n request: FacetsInitialRequest | FacetsEntitiesResponse,\n): request is FacetsEntitiesResponse {\n return !!(request as FacetsEntitiesResponse).cursor;\n}\n\nfunction encodeCursor({\n entities,\n limit,\n payload,\n}: {\n entities: Entity[];\n limit: number;\n payload: { text: string; start: number };\n}) {\n if (entities.length > limit) {\n return { cursor: btoa(JSON.stringify(payload)) };\n }\n return {};\n}\n\nfunction filterEntity(text: string, entity: Entity) {\n const normalizedText = text.trim();\n return (\n entity.kind.includes(normalizedText) ||\n entity.metadata.namespace?.includes(normalizedText) ||\n entity.metadata.name.includes(normalizedText)\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 { makeStyles } from '@material-ui/core/styles';\nimport { EntityTagFilter } from '../../filters';\nimport { EntityAutocompletePicker } from '../EntityAutocompletePicker/EntityAutocompletePicker';\nimport { catalogReactTranslationRef } from '../../translation';\nimport { useTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/** @public */\nexport type CatalogReactEntityTagPickerClassKey = 'input';\n\n/** @public */\nexport type EntityTagPickerProps = {\n showCounts?: boolean;\n initialFilter?: string[];\n hidden?: boolean;\n};\n\nconst useStyles = makeStyles(\n { input: {} },\n { name: 'CatalogReactEntityTagPicker' },\n);\n\n/** @public */\nexport const EntityTagPicker = (props: EntityTagPickerProps) => {\n const classes = useStyles();\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n return (\n <EntityAutocompletePicker\n label={t('entityTagPicker.title')}\n name=\"tags\"\n path=\"metadata.tags\"\n Filter={EntityTagFilter}\n showCounts={props.showCounts}\n InputProps={{ className: classes.input }}\n initialSelectedOptions={props.initialFilter ? props.initialFilter : []}\n hidden={props.hidden}\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 {\n configApiRef,\n IconComponent,\n useApi,\n} from '@backstage/core-plugin-api';\nimport Card from '@material-ui/core/Card';\nimport List from '@material-ui/core/List';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemSecondaryAction from '@material-ui/core/ListItemSecondaryAction';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport MenuItem from '@material-ui/core/MenuItem';\nimport Typography from '@material-ui/core/Typography';\nimport { makeStyles } from '@material-ui/core/styles';\nimport SettingsIcon from '@material-ui/icons/Settings';\nimport { StarIcon } from '@backstage/core-components';\nimport { Fragment, useEffect, useMemo, useState } from 'react';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { UserListFilterKind } from '../../types';\nimport { useOwnedEntitiesCount } from './useOwnedEntitiesCount';\nimport { useAllEntitiesCount } from './useAllEntitiesCount';\nimport { useStarredEntitiesCount } from './useStarredEntitiesCount';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type CatalogReactUserListPickerClassKey =\n | 'root'\n | 'title'\n | 'listIcon'\n | 'menuItem'\n | 'groupWrapper';\n\nconst useStyles = makeStyles(\n theme => ({\n root: {\n backgroundColor: 'rgba(0, 0, 0, .11)',\n boxShadow: 'none',\n margin: theme.spacing(1, 0, 1, 0),\n },\n title: {\n margin: theme.spacing(1, 0, 0, 1),\n textTransform: 'uppercase',\n fontSize: 12,\n fontWeight: 'bold',\n },\n listIcon: {\n minWidth: 30,\n color: theme.palette.text.primary,\n },\n menuItem: {\n minHeight: theme.spacing(6),\n },\n groupWrapper: {\n margin: theme.spacing(1, 1, 2, 1),\n },\n }),\n { name: 'CatalogReactUserListPicker' },\n);\n\nexport type ButtonGroup = {\n name: string;\n items: {\n id: 'owned' | 'starred' | 'all';\n label: string;\n icon?: IconComponent;\n }[];\n};\n\nfunction getFilterGroups(\n orgName: string,\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n): ButtonGroup[] {\n return [\n {\n name: t('userListPicker.personalFilter.title'),\n items: [\n {\n id: 'owned',\n label: t('userListPicker.personalFilter.ownedLabel'),\n icon: SettingsIcon,\n },\n {\n id: 'starred',\n label: t('userListPicker.personalFilter.starredLabel'),\n icon: StarIcon,\n },\n ],\n },\n {\n name: orgName,\n items: [\n {\n id: 'all',\n label: t('userListPicker.orgFilterAllLabel'),\n },\n ],\n },\n ];\n}\n\n/** @public */\nexport type UserListPickerProps = {\n initialFilter?: UserListFilterKind;\n availableFilters?: UserListFilterKind[];\n hidden?: boolean;\n alwaysKeepFilters?: boolean;\n};\n\n/** @public */\nexport const UserListPicker = (props: UserListPickerProps) => {\n const { initialFilter, availableFilters, hidden, alwaysKeepFilters } = props;\n const classes = useStyles();\n const configApi = useApi(configApiRef);\n const { t } = useTranslationRef(catalogReactTranslationRef);\n const orgName =\n configApi.getOptionalString('organization.name') ??\n t('userListPicker.defaultOrgName');\n const {\n filters,\n updateFilters,\n queryParameters: { user: userParameter },\n } = useEntityList();\n const kindParameter = filters.kind?.value?.toLowerCase();\n\n // Remove group items that aren't in availableFilters and exclude\n // any now-empty groups.\n const userAndGroupFilterIds = ['starred', 'all'];\n const filterGroups = getFilterGroups(orgName, t)\n .map(filterGroup => ({\n ...filterGroup,\n items: filterGroup.items.filter(({ id }) =>\n // TODO: avoid hardcoding kinds here\n ['group', 'user'].some(kind => kind === kindParameter)\n ? userAndGroupFilterIds.includes(id)\n : !availableFilters || availableFilters.includes(id),\n ),\n }))\n .filter(({ items }) => !!items.length);\n\n const {\n count: ownedEntitiesCount,\n loading: loadingOwnedEntities,\n filter: ownedEntitiesFilter,\n } = useOwnedEntitiesCount();\n const { count: allCount } = useAllEntitiesCount();\n const {\n count: starredEntitiesCount,\n filter: starredEntitiesFilter,\n loading: loadingStarredEntities,\n } = useStarredEntitiesCount();\n\n const queryParamUserFilter = useMemo(\n () => [userParameter].flat()[0],\n [userParameter],\n );\n\n const [selectedUserFilter, setSelectedUserFilter] = useState(\n (queryParamUserFilter as UserListFilterKind) ?? initialFilter,\n );\n\n const filterCounts = useMemo(() => {\n return {\n all: allCount,\n starred: starredEntitiesCount,\n owned: ownedEntitiesCount,\n };\n }, [starredEntitiesCount, ownedEntitiesCount, allCount]);\n\n // Set selected user filter on query parameter updates; this happens at initial page load and from\n // external updates to the page location.\n useEffect(() => {\n if (queryParamUserFilter) {\n setSelectedUserFilter(queryParamUserFilter as UserListFilterKind);\n }\n }, [queryParamUserFilter]);\n\n const loading = loadingOwnedEntities || loadingStarredEntities;\n\n useEffect(() => {\n if (\n !loading &&\n !!selectedUserFilter &&\n selectedUserFilter !== 'all' &&\n filterCounts[selectedUserFilter] === 0 &&\n !alwaysKeepFilters\n ) {\n setSelectedUserFilter('all');\n }\n }, [\n loading,\n filterCounts,\n selectedUserFilter,\n setSelectedUserFilter,\n alwaysKeepFilters,\n ]);\n\n useEffect(() => {\n if (!selectedUserFilter) {\n return;\n }\n if (loading) {\n return;\n }\n\n const getFilter = () => {\n if (selectedUserFilter === 'owned') {\n return ownedEntitiesFilter;\n }\n if (selectedUserFilter === 'starred') {\n return starredEntitiesFilter;\n }\n return EntityUserFilter.all();\n };\n\n updateFilters({ user: getFilter() });\n }, [\n selectedUserFilter,\n starredEntitiesFilter,\n ownedEntitiesFilter,\n updateFilters,\n\n loading,\n ]);\n\n return hidden ? null : (\n <Card className={classes.root}>\n {filterGroups.map(group => (\n <Fragment key={group.name}>\n <Typography\n variant=\"subtitle2\"\n component=\"span\"\n className={classes.title}\n >\n {group.name}\n </Typography>\n <Card className={classes.groupWrapper}>\n <List disablePadding dense role=\"menu\" aria-label={group.name}>\n {group.items.map((item, index) => (\n <MenuItem\n role=\"none presentation\"\n key={item.id}\n divider={index !== group.items.length - 1}\n onClick={() => setSelectedUserFilter(item.id)}\n selected={item.id === filters.user?.value}\n className={classes.menuItem}\n disabled={filterCounts[item.id] === 0}\n data-testid={`user-picker-${item.id}`}\n tabIndex={0}\n ContainerProps={{ role: 'menuitem' }}\n >\n {item.icon && (\n <ListItemIcon className={classes.listIcon}>\n <item.icon fontSize=\"small\" />\n </ListItemIcon>\n )}\n <ListItemText>\n <Typography variant=\"body1\">{item.label} </Typography>\n </ListItemText>\n <ListItemSecondaryAction>\n {filterCounts[item.id] ?? '-'}\n </ListItemSecondaryAction>\n </MenuItem>\n ))}\n </List>\n </Card>\n </Fragment>\n ))}\n </Card>\n );\n};\n","/*\n * Copyright 2023 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 { identityApiRef, useApi } from '@backstage/core-plugin-api';\nimport { compact, intersection } from 'lodash';\nimport { useMemo } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityOwnerFilter, EntityUserFilter } from '../../filters';\nimport { useEntityList } from '../../hooks';\nimport { CatalogFilters, reduceCatalogFilters } from '../../utils/filters';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDeepCompareEffect from 'react-use/esm/useDeepCompareEffect';\n\nexport function useOwnedEntitiesCount() {\n const identityApi = useApi(identityApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n const { filters } = useEntityList();\n\n const { value: ownershipEntityRefs, loading: loadingEntityRefs } = useAsync(\n async () => (await identityApi.getBackstageIdentity()).ownershipEntityRefs,\n // load only on mount\n [],\n );\n\n const { user, owners, ...allFilters } = filters;\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(\n compact(Object.values(allFilters)),\n );\n\n const [{ value: count, loading: loadingEntityOwnership }, fetchEntities] =\n useAsyncFn(\n async (req: {\n ownershipEntityRefs: string[];\n owners: EntityOwnerFilter | undefined;\n filter: CatalogFilters;\n }) => {\n const ownedClaims = getOwnedCountClaims(\n req.owners,\n req.ownershipEntityRefs,\n );\n if (ownedClaims === undefined) {\n // this implicitly means that there aren't claims in common with\n // the logged in users, so avoid invoking the queryEntities endpoint\n // which will implicitly returns 0\n return 0;\n }\n\n const { ['metadata.name']: metadata, ...filter } = req.filter.filter;\n\n const { totalItems } = await catalogApi.queryEntities({\n ...req.filter,\n filter: {\n ...filter,\n 'relations.ownedBy': ownedClaims,\n },\n limit: 0,\n });\n return totalItems;\n },\n [],\n { loading: true },\n );\n\n useDeepCompareEffect(() => {\n // context contains no filter, wait\n if (Object.keys(catalogFilters.filter).length === 0) {\n return;\n }\n // ownershipEntityRefs is loading, wait\n if (ownershipEntityRefs === undefined) {\n return;\n }\n fetchEntities({\n ownershipEntityRefs,\n owners,\n filter: catalogFilters,\n });\n }, [ownershipEntityRefs, owners, catalogFilters]);\n\n const loading = loadingEntityRefs || loadingEntityOwnership;\n\n return {\n count,\n loading,\n filter: useMemo(\n () => EntityUserFilter.owned(ownershipEntityRefs ?? []),\n [ownershipEntityRefs],\n ),\n ownershipEntityRefs,\n };\n}\n\nfunction getOwnedCountClaims(\n owners: EntityOwnerFilter | undefined,\n ownershipEntityRefs: string[] | undefined,\n) {\n if (ownershipEntityRefs === undefined) {\n return undefined;\n }\n const ownersRefs = owners?.values ?? [];\n if (ownersRefs.length) {\n const commonOwnedBy = intersection(ownersRefs, ownershipEntityRefs);\n if (commonOwnedBy.length === 0) {\n return undefined;\n }\n return commonOwnedBy;\n }\n return ownershipEntityRefs;\n}\n","/*\n * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { useEntityList } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useAllEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n limit: 0,\n };\n\n if (Object.keys(catalogFilters.filter).length === 0) {\n prevRequest.current = undefined;\n return prevRequest.current;\n }\n\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n return newRequest;\n }, [filters]);\n\n const { value: count, loading } = useAsync(async () => {\n if (request === undefined) {\n return 0;\n }\n const { totalItems } = await catalogApi.queryEntities(request);\n\n return totalItems;\n }, [request]);\n\n return { count, loading };\n}\n","/*\n * Copyright 2023 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 { QueryEntitiesInitialRequest } from '@backstage/catalog-client';\nimport { parseEntityRef, stringifyEntityRef } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { compact, isEqual } from 'lodash';\nimport { useMemo, useRef } from 'react';\nimport useAsync from 'react-use/esm/useAsync';\nimport { catalogApiRef } from '../../api';\nimport { EntityUserFilter } from '../../filters';\nimport { useEntityList, useStarredEntities } from '../../hooks';\nimport { reduceCatalogFilters } from '../../utils/filters';\n\nexport function useStarredEntitiesCount() {\n const catalogApi = useApi(catalogApiRef);\n const { filters } = useEntityList();\n const { starredEntities } = useStarredEntities();\n\n const prevRequest = useRef<QueryEntitiesInitialRequest>();\n const request = useMemo(() => {\n const { user, ...allFilters } = filters;\n const compacted = compact(Object.values(allFilters));\n const { orderFields, ...catalogFilters } = reduceCatalogFilters(compacted);\n\n const facet = 'metadata.name';\n\n const newRequest: QueryEntitiesInitialRequest = {\n ...catalogFilters,\n filter: {\n ...catalogFilters.filter,\n /**\n * here we are filtering entities by `name`. Given this filter,\n * the response might contain more entities than expected, in case multiple entities\n * of different kind or namespace share the same name. Those extra entities are filtered out\n * client side by `EntityUserFilter`, so they won't be visible to the user.\n */\n [facet]: Array.from(starredEntities).map(e => parseEntityRef(e).name),\n },\n /**\n * limit is set to a high value as we are not expecting many starred entities\n */\n limit: 1000,\n };\n if (isEqual(newRequest, prevRequest.current)) {\n return prevRequest.current;\n }\n prevRequest.current = newRequest;\n\n return newRequest;\n }, [filters, starredEntities]);\n\n const { value: count, loading } = useAsync(async () => {\n if (!starredEntities.size) {\n return 0;\n }\n\n /**\n * given a list of starred entity refs and some filters coming from CatalogPage,\n * it reduces the list of starred entities, to a list of entities that matches the\n * provided filters. It won't be possible to getEntitiesByRefs\n * as the method doesn't accept any filter.\n */\n const response = await catalogApi.queryEntities(request);\n\n return response.items\n .map(e =>\n stringifyEntityRef({\n kind: e.kind,\n namespace: e.metadata.namespace,\n name: e.metadata.name,\n }),\n )\n .filter(e => starredEntities.has(e)).length;\n }, [request, starredEntities]);\n\n const filter = useMemo(\n () => EntityUserFilter.starred(Array.from(starredEntities)),\n [starredEntities],\n );\n\n return { count, loading, filter };\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 {\n Entity,\n parseEntityRef,\n RELATION_OWNED_BY,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { AlphaEntity } from '@backstage/catalog-model/alpha';\nimport { EntityFilter, UserListFilterKind } from './types';\nimport { getEntityRelations } from './utils/getEntityRelations';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\n/**\n * Filter entities based on Kind.\n * @public\n */\nexport class EntityKindFilter implements EntityFilter {\n readonly value: string;\n readonly label: string;\n\n constructor(value: string, label: string) {\n this.value = value;\n this.label = label;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { kind: this.value };\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on type\n * @public\n */\nexport class EntityTypeFilter implements EntityFilter {\n readonly value: string | string[];\n\n constructor(value: string | string[]) {\n this.value = value;\n }\n\n // Simplify `string | string[]` for consumers, always returns an array\n getTypes(): string[] {\n return Array.isArray(this.value) ? this.value : [this.value];\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.type': this.getTypes() };\n }\n\n toQueryValue(): string[] {\n return this.getTypes();\n }\n}\n\n/**\n * Filters entities based on tag.\n * @public\n */\nexport class EntityTagFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.every(v => (entity.metadata.tags ?? []).includes(v));\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.tags': this.values };\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities where the text matches spec, title or tags.\n * @public\n */\nexport class EntityTextFilter implements EntityFilter {\n readonly value: string;\n\n constructor(value: string) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const words = this.toUpperArray(this.value.split(/\\s/));\n const exactMatch = this.toUpperArray([entity.metadata.tags]);\n const partialMatch = this.toUpperArray([\n entity.metadata.name,\n entity.metadata.title,\n (entity.spec?.profile as { displayName?: string })?.displayName,\n ]);\n\n for (const word of words) {\n if (\n exactMatch.every(m => m !== word) &&\n partialMatch.every(m => !m.includes(word))\n ) {\n return false;\n }\n }\n\n return true;\n }\n\n getFullTextFilters() {\n return {\n term: this.value,\n // Update this to be more dynamic based on table columns.\n fields: ['metadata.name', 'metadata.title', 'spec.profile.displayName'],\n };\n }\n\n toQueryValue() {\n return this.value;\n }\n\n private toUpperArray(\n value: Array<string | string[] | undefined>,\n ): Array<string> {\n return value\n .flat()\n .filter((m): m is string => Boolean(m))\n .map(m => m.toLocaleUpperCase('en-US'));\n }\n}\n\n/**\n * Filter matching entities that are owned by group.\n * @public\n *\n * CAUTION: This class may contain both full and partial entity refs.\n */\nexport class EntityOwnerFilter implements EntityFilter {\n readonly values: string[];\n constructor(values: string[]) {\n this.values = values.reduce((fullRefs, ref) => {\n // Attempt to remove bad entity references here.\n try {\n fullRefs.push(\n stringifyEntityRef(parseEntityRef(ref, { defaultKind: 'Group' })),\n );\n return fullRefs;\n } catch (err) {\n return fullRefs;\n }\n }, [] as string[]);\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'relations.ownedBy': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v =>\n getEntityRelations(entity, RELATION_OWNED_BY).some(\n o => stringifyEntityRef(o) === v,\n ),\n );\n }\n\n /**\n * Get the URL query parameter value. May be a mix of full and humanized entity refs.\n * @returns list of entity refs.\n */\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities on lifecycle.\n * @public\n */\nexport class EntityLifecycleFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'spec.lifecycle': this.values };\n }\n\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.spec?.lifecycle === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * Filters entities to those within the given namespace(s).\n * @public\n */\nexport class EntityNamespaceFilter implements EntityFilter {\n readonly values: string[];\n\n constructor(values: string[]) {\n this.values = values;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n return { 'metadata.namespace': this.values };\n }\n filterEntity(entity: Entity): boolean {\n return this.values.some(v => entity.metadata.namespace === v);\n }\n\n toQueryValue(): string[] {\n return this.values;\n }\n}\n\n/**\n * @public\n */\nexport class EntityUserFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly refs?: string[];\n\n private constructor(value: UserListFilterKind, refs?: string[]) {\n this.value = value;\n this.refs = refs;\n }\n\n static owned(ownershipEntityRefs: string[]) {\n return new EntityUserFilter('owned', ownershipEntityRefs);\n }\n\n static all() {\n return new EntityUserFilter('all');\n }\n\n static starred(starredEntityRefs: string[]) {\n return new EntityUserFilter('starred', starredEntityRefs);\n }\n\n getCatalogFilters(): Record<string, string[]> {\n if (this.value === 'owned') {\n return { 'relations.ownedBy': this.refs ?? [] };\n }\n if (this.value === 'starred') {\n return {\n 'metadata.name': this.refs?.map(e => parseEntityRef(e).name) ?? [],\n };\n }\n return {};\n }\n\n filterEntity(entity: Entity) {\n if (this.value === 'starred') {\n return this.refs?.includes(stringifyEntityRef(entity)) ?? true;\n }\n // used only for retro-compatibility with non paginated data.\n // This is supposed to return always true for paginated\n // owned entities, since the filters are applied server side.\n if (this.value === 'owned') {\n const relations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n this.refs?.some(v =>\n relations.some(o => stringifyEntityRef(o) === v),\n ) ?? false\n );\n }\n return true;\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based on whatever the user has starred or owns them.\n * @deprecated use EntityUserFilter\n * @public\n */\nexport class UserListFilter implements EntityFilter {\n readonly value: UserListFilterKind;\n readonly isOwnedEntity: (entity: Entity) => boolean;\n readonly isStarredEntity: (entity: Entity) => boolean;\n\n constructor(\n value: UserListFilterKind,\n isOwnedEntity: (entity: Entity) => boolean,\n isStarredEntity: (entity: Entity) => boolean,\n ) {\n this.value = value;\n this.isOwnedEntity = isOwnedEntity;\n this.isStarredEntity = isStarredEntity;\n }\n\n filterEntity(entity: Entity): boolean {\n switch (this.value) {\n case 'owned':\n return this.isOwnedEntity(entity);\n case 'starred':\n return this.isStarredEntity(entity);\n default:\n return true;\n }\n }\n\n toQueryValue(): string {\n return this.value;\n }\n}\n\n/**\n * Filters entities based if it is an orphan or not.\n * @public\n */\nexport class EntityOrphanFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n getCatalogFilters(): Record<string, string | string[]> {\n if (this.value) {\n return { 'metadata.annotations.backstage.io/orphan': String(this.value) };\n }\n return {};\n }\n\n filterEntity(entity: Entity): boolean {\n const orphan = entity.metadata.annotations?.['backstage.io/orphan'];\n return orphan !== undefined && this.value.toString() === orphan;\n }\n}\n\n/**\n * Filters entities based on if it has errors or not.\n * @public\n */\nexport class EntityErrorFilter implements EntityFilter {\n readonly value: boolean;\n\n constructor(value: boolean) {\n this.value = value;\n }\n\n filterEntity(entity: Entity): boolean {\n const error =\n ((entity as AlphaEntity)?.status?.items?.length as number) > 0;\n return error !== undefined && this.value === error;\n }\n}\n\n/**\n * Sort entities by a given field/column.\n * @public\n */\nexport class EntityOrderFilter implements EntityFilter {\n readonly values: [string, 'asc' | 'desc'][];\n\n constructor(values: [string, 'asc' | 'desc'][]) {\n this.values = values;\n }\n\n getOrderFilters(): EntityOrderQuery {\n return this.values.map(([field, order]) => ({ field, order }));\n }\n\n toQueryValue(): string[] {\n return this.values.flat();\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 { QueryEntitiesResponse } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport {\n createVersionedContext,\n createVersionedValueMap,\n useVersionedContext,\n} from '@backstage/version-bridge';\nimport { compact, isEqual } from 'lodash';\nimport qs from 'qs';\nimport {\n createContext,\n PropsWithChildren,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n} from 'react';\nimport { useLocation } from 'react-router-dom';\nimport useAsyncFn from 'react-use/esm/useAsyncFn';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport useMountedState from 'react-use/esm/useMountedState';\nimport { catalogApiRef } from '../api';\nimport {\n EntityErrorFilter,\n EntityKindFilter,\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityTypeFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityFilter, EntityListPagination } from '../types';\nimport {\n reduceBackendCatalogFilters,\n reduceCatalogFilters,\n reduceEntityFilters,\n} from '../utils/filters';\n\n/** @public */\nexport type DefaultEntityFilters = {\n kind?: EntityKindFilter;\n type?: EntityTypeFilter;\n user?: UserListFilter | EntityUserFilter;\n owners?: EntityOwnerFilter;\n lifecycles?: EntityLifecycleFilter;\n tags?: EntityTagFilter;\n text?: EntityTextFilter;\n orphan?: EntityOrphanFilter;\n error?: EntityErrorFilter;\n namespace?: EntityNamespaceFilter;\n order?: EntityOrderFilter;\n};\n\n/** @public */\nexport type PaginationMode = 'cursor' | 'offset' | 'none';\n\n/** @public */\nexport type EntityListContextProps<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n> = {\n /**\n * The currently registered filters, adhering to the shape of DefaultEntityFilters or an extension\n * of that default (to add custom filter types).\n */\n filters: EntityFilters;\n\n /**\n * The resolved list of catalog entities, after all filters are applied.\n */\n entities: Entity[];\n\n /**\n * The resolved list of catalog entities, after _only catalog-backend_ filters are applied.\n */\n backendEntities: Entity[];\n\n /**\n * Update one or more of the registered filters. Optional filters can be set to `undefined` to\n * reset the filter.\n */\n updateFilters: (\n filters:\n | Partial<EntityFilters>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => void;\n\n /**\n * Filter values from query parameters.\n */\n queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;\n\n loading: boolean;\n error?: Error;\n\n pageInfo?: {\n next?: () => void;\n prev?: () => void;\n };\n totalItems?: number;\n limit: number;\n offset?: number;\n setLimit: (limit: number) => void;\n setOffset?: (offset: number) => void;\n paginationMode: PaginationMode;\n};\n\n// This context has support for multiple concurrent versions of this package.\n// It is currently used in parallel with the old context in order to provide\n// a smooth transition, but will eventually be the only context we use.\nexport const NewEntityListContext = createVersionedContext<{\n 1: EntityListContextProps<any>;\n}>('entity-list-context');\n\n/**\n * Creates new context for entity listing and filtering.\n */\nexport const OldEntityListContext = createContext<\n EntityListContextProps<any> | undefined\n>(undefined);\n\ntype OutputState<EntityFilters extends DefaultEntityFilters> = {\n appliedFilters: EntityFilters;\n appliedCursor?: string;\n entities: Entity[];\n backendEntities: Entity[];\n pageInfo?: QueryEntitiesResponse['pageInfo'];\n totalItems?: number;\n offset?: number;\n limit?: number;\n};\n\n/**\n * @public\n */\nexport type EntityListProviderProps = PropsWithChildren<{\n pagination?: EntityListPagination;\n}>;\n\n/**\n * Provides entities and filters for a catalog listing.\n * @public\n */\nexport const EntityListProvider = <EntityFilters extends DefaultEntityFilters>(\n props: EntityListProviderProps,\n) => {\n const isMounted = useMountedState();\n const catalogApi = useApi(catalogApiRef);\n const [requestedFilters, setRequestedFilters] = useState<EntityFilters>(\n {} as EntityFilters,\n );\n\n // We use react-router's useLocation hook so updates from external sources trigger an update to\n // the queryParameters in outputState. Updates from this hook use replaceState below and won't\n // trigger a useLocation change; this would instead come from an external source, such as a manual\n // update of the URL or two catalog sidebar links with different catalog filters.\n const location = useLocation();\n\n const getPaginationMode = (): PaginationMode => {\n if (props.pagination === true) {\n return 'cursor';\n }\n return typeof props.pagination === 'object'\n ? props.pagination.mode ?? 'cursor'\n : 'none';\n };\n\n const paginationMode = getPaginationMode();\n const paginationLimit =\n typeof props.pagination === 'object' ? props.pagination.limit ?? 20 : 20;\n\n const {\n queryParameters,\n cursor: initialCursor,\n offset: initialOffset,\n limit: initialLimit,\n } = useMemo(() => {\n const parsed = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n\n let limit = paginationLimit;\n if (typeof parsed.limit === 'string') {\n const queryLimit = Number.parseInt(parsed.limit, 10);\n if (!isNaN(queryLimit)) {\n limit = queryLimit;\n }\n }\n\n const offset =\n typeof parsed.offset === 'string' && paginationMode === 'offset'\n ? Number.parseInt(parsed.offset, 10)\n : undefined;\n\n return {\n queryParameters: (parsed.filters ?? {}) as Record<\n string,\n string | string[]\n >,\n cursor:\n typeof parsed.cursor === 'string' && paginationMode === 'cursor'\n ? parsed.cursor\n : undefined,\n offset:\n paginationMode === 'offset' && offset && !isNaN(offset)\n ? offset\n : undefined,\n limit,\n };\n }, [paginationMode, location.search, paginationLimit]);\n\n const [cursor, setCursor] = useState(initialCursor);\n const [offset, setOffset] = useState<number | undefined>(initialOffset);\n const [limit, setLimit] = useState(initialLimit);\n\n const [outputState, setOutputState] = useState<OutputState<EntityFilters>>(\n () => {\n return {\n appliedFilters: {} as EntityFilters,\n entities: [],\n backendEntities: [],\n pageInfo: {},\n offset,\n limit,\n };\n },\n );\n\n // The main async filter worker. Note that while it has a lot of dependencies\n // in terms of its implementation, the triggering only happens (debounced)\n // based on the requested filters changing.\n const [{ value: resolvedValue, loading, error }, refresh] = useAsyncFn(\n async () => {\n const kindValue =\n requestedFilters.kind?.value?.toLocaleLowerCase('en-US');\n const adjustedFilters =\n kindValue === 'user' || kindValue === 'group'\n ? { ...requestedFilters, owners: undefined }\n : requestedFilters;\n const compacted = compact(Object.values(adjustedFilters));\n const entityFilter = reduceEntityFilters(compacted);\n\n if (paginationMode !== 'none') {\n if (cursor) {\n if (cursor !== outputState.appliedCursor) {\n const response = await catalogApi.queryEntities({\n cursor,\n limit,\n });\n return {\n appliedFilters: requestedFilters,\n appliedCursor: cursor,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n appliedCursor: outputState.appliedCursor,\n backendEntities: outputState.backendEntities,\n entities,\n pageInfo: outputState.pageInfo,\n totalItems: outputState.totalItems,\n limit: outputState.limit,\n offset: outputState.offset,\n };\n }\n\n const backendFilter = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n if (\n (paginationMode === 'offset' &&\n (outputState.limit !== limit || outputState.offset !== offset)) ||\n !isEqual(previousBackendFilter, backendFilter)\n ) {\n const response = await catalogApi.queryEntities({\n ...backendFilter,\n limit,\n offset,\n });\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities: response.items.filter(entityFilter),\n pageInfo: response.pageInfo,\n totalItems: response.totalItems,\n limit,\n offset,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n pageInfo: outputState.pageInfo,\n totalItems: outputState.totalItems,\n limit: outputState.limit,\n offset: outputState.offset,\n };\n }\n\n const backendFilter = reduceBackendCatalogFilters(compacted);\n const { orderFields } = reduceCatalogFilters(compacted);\n const previousBackendFilter = reduceBackendCatalogFilters(\n compact(Object.values(outputState.appliedFilters)),\n );\n\n // TODO(mtlewis): currently entities will never be requested unless\n // there's at least one filter, we should allow an initial request\n // to happen with no filters.\n if (!isEqual(previousBackendFilter, backendFilter)) {\n // TODO(timbonicus): should limit fields here, but would need filter\n // fields + table columns\n const response = await catalogApi.getEntities({\n filter: backendFilter,\n order: orderFields,\n });\n const entities = response.items.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: response.items,\n entities,\n totalItems: entities.length,\n };\n }\n const entities = outputState.backendEntities.filter(entityFilter);\n return {\n appliedFilters: requestedFilters,\n backendEntities: outputState.backendEntities,\n entities,\n totalItems: entities.length,\n };\n },\n [\n catalogApi,\n queryParameters,\n requestedFilters,\n outputState,\n cursor,\n paginationMode,\n limit,\n offset,\n ],\n { loading: true },\n );\n\n // Slight debounce on the refresh, since (especially on page load) several\n // filters will be calling this in rapid succession.\n useDebounce(refresh, 10, [requestedFilters, cursor, limit, offset]);\n\n useEffect(() => {\n if (resolvedValue === undefined) {\n return;\n }\n setOutputState(resolvedValue);\n if (isMounted()) {\n const queryParams = Object.keys(requestedFilters).reduce(\n (params, key) => {\n const filter = requestedFilters[key as keyof EntityFilters] as\n | EntityFilter\n | undefined;\n if (filter?.toQueryValue) {\n params[key] = filter.toQueryValue();\n }\n return params;\n },\n {} as Record<string, string | string[]>,\n );\n\n const oldParams = qs.parse(location.search, {\n ignoreQueryPrefix: true,\n arrayLimit: 10000,\n });\n const newParams = qs.stringify(\n {\n ...oldParams,\n filters: queryParams,\n ...(paginationMode === 'none' ? {} : { cursor, limit, offset }),\n },\n { addQueryPrefix: true, arrayFormat: 'repeat' },\n );\n const newUrl = `${window.location.pathname}${newParams}`;\n // We use direct history manipulation since useSearchParams and\n // useNavigate in react-router-dom cause unnecessary extra rerenders.\n // Also make sure to replace the state rather than pushing, since we\n // don't want there to be back/forward slots for every single filter\n // change.\n window.history?.replaceState(null, document.title, newUrl);\n }\n }, [\n cursor,\n isMounted,\n limit,\n location.search,\n offset,\n requestedFilters,\n resolvedValue,\n paginationMode,\n ]);\n\n const updateFilters = useCallback(\n (\n update:\n | Partial<EntityFilter>\n | ((prevFilters: EntityFilters) => Partial<EntityFilters>),\n ) => {\n // changing filters will affect pagination, so we need to reset\n // the cursor and start from the first page.\n // TODO(vinzscam): this is currently causing issues at page reload\n // where the state is not kept. Unfortunately we need to rethink\n // the way filters work in order to fix this.\n if (paginationMode === 'cursor') {\n setCursor(undefined);\n } else if (paginationMode === 'offset') {\n // Same thing with offset\n setOffset(0);\n }\n setRequestedFilters(prevFilters => {\n const newFilters =\n typeof update === 'function' ? update(prevFilters) : update;\n return { ...prevFilters, ...newFilters };\n });\n },\n [paginationMode],\n );\n\n // Use resolvedValue directly when available to avoid an extra render cycle.\n // Without this, there's a render where loading has flipped back to false but\n // outputState hasn't been updated yet (it syncs via useEffect), causing a\n // flash of stale data between the loading state and the new results.\n const latestOutput = resolvedValue ?? outputState;\n\n const pageInfo = useMemo(() => {\n if (paginationMode !== 'cursor') {\n return undefined;\n }\n\n const prevCursor = latestOutput.pageInfo?.prevCursor;\n const nextCursor = latestOutput.pageInfo?.nextCursor;\n return {\n prev: prevCursor ? () => setCursor(prevCursor) : undefined,\n next: nextCursor ? () => setCursor(nextCursor) : undefined,\n };\n }, [paginationMode, latestOutput.pageInfo]);\n\n const value = useMemo(\n () => ({\n filters: latestOutput.appliedFilters,\n entities: latestOutput.entities,\n backendEntities: latestOutput.backendEntities,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n totalItems: latestOutput.totalItems,\n limit,\n offset,\n setLimit,\n setOffset,\n paginationMode,\n }),\n [\n latestOutput,\n updateFilters,\n queryParameters,\n loading,\n error,\n pageInfo,\n limit,\n offset,\n paginationMode,\n setLimit,\n setOffset,\n ],\n );\n\n return (\n <OldEntityListContext.Provider value={value}>\n <NewEntityListContext.Provider\n value={createVersionedValueMap({ 1: value })}\n >\n {props.children}\n </NewEntityListContext.Provider>\n </OldEntityListContext.Provider>\n );\n};\n\n/**\n * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.\n * @public\n */\nexport function useEntityList<\n EntityFilters extends DefaultEntityFilters = DefaultEntityFilters,\n>(): EntityListContextProps<EntityFilters> {\n const versionedHolder = useVersionedContext<{\n 1: EntityListContextProps<any>;\n }>('entity-list-context');\n const oldContext = useContext(OldEntityListContext);\n\n if (versionedHolder) {\n const value = versionedHolder.atVersion(1);\n if (!value) {\n throw new Error('EntityListContext v1 not available');\n }\n return value;\n }\n\n if (oldContext) {\n return oldContext;\n }\n\n throw new Error('useEntityList must be used within EntityListProvider');\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 {\n Entity,\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { useApi } from '@backstage/core-plugin-api';\nimport { useCallback, useMemo } from 'react';\nimport useObservable from 'react-use/esm/useObservable';\nimport { starredEntitiesApiRef } from '../apis';\n\nfunction getEntityRef(\n entityOrRef: Entity | CompoundEntityRef | string,\n): string {\n return typeof entityOrRef === 'string'\n ? entityOrRef\n : stringifyEntityRef(entityOrRef);\n}\n\n/** @public */\nexport function useStarredEntities(): {\n starredEntities: Set<string>;\n toggleStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => void;\n isStarredEntity: (\n entityOrRef: Entity | CompoundEntityRef | string,\n ) => boolean;\n} {\n const starredEntitiesApi = useApi(starredEntitiesApiRef);\n\n const starredEntities = useObservable(\n useMemo(() => starredEntitiesApi.starredEntitie$(), [starredEntitiesApi]),\n new Set<string>(),\n );\n\n const isStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntities.has(getEntityRef(entityOrRef)),\n [starredEntities],\n );\n\n const toggleStarredEntity = useCallback(\n (entityOrRef: Entity | CompoundEntityRef | string) =>\n starredEntitiesApi.toggleStarred(getEntityRef(entityOrRef)).then(),\n [starredEntitiesApi],\n );\n\n return {\n starredEntities,\n toggleStarredEntity,\n isStarredEntity,\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 { Entity } from '@backstage/catalog-model';\nimport { EntityFilter } from '../types';\nimport {\n EntityLifecycleFilter,\n EntityNamespaceFilter,\n EntityOrderFilter,\n EntityOrphanFilter,\n EntityOwnerFilter,\n EntityTagFilter,\n EntityTextFilter,\n EntityUserFilter,\n UserListFilter,\n} from '../filters';\nimport { EntityOrderQuery } from '@backstage/catalog-client';\n\nexport interface CatalogFilters {\n filter: Record<string, string | symbol | (string | symbol)[]>;\n fullTextFilter?: {\n term: string;\n };\n orderFields?: EntityOrderQuery;\n}\n\nfunction isEntityTextFilter(t: EntityFilter): t is EntityTextFilter {\n return !!(t as EntityTextFilter).getFullTextFilters;\n}\n\nfunction isEntityOrderFilter(t: EntityFilter): t is EntityOrderFilter {\n return !!(t as EntityOrderFilter).getOrderFilters;\n}\n\nexport function reduceCatalogFilters(filters: EntityFilter[]): CatalogFilters {\n const condensedFilters = filters.reduce<CatalogFilters['filter']>(\n (compoundFilter, filter) => {\n return {\n ...compoundFilter,\n ...(filter.getCatalogFilters ? filter.getCatalogFilters() : {}),\n };\n },\n {},\n );\n\n const fullTextFilter = filters.find(isEntityTextFilter)?.getFullTextFilters();\n\n const orderFields = filters.find(isEntityOrderFilter)?.getOrderFilters() || [\n {\n field: 'metadata.name',\n order: 'asc',\n },\n ];\n return { filter: condensedFilters, fullTextFilter, orderFields };\n}\n\n/**\n * This function computes and returns an object containing the filters to be sent\n * to the backend. Any filter coming from `EntityKindFilter` and `EntityTypeFilter`, together\n * with custom filter set by the adopters is allowed. This function is used by `EntityListProvider`\n * and it won't be needed anymore in the future once pagination is implemented, as all the filters\n * will be applied backend-side.\n */\nexport function reduceBackendCatalogFilters(filters: EntityFilter[]) {\n const backendCatalogFilters: Record<\n string,\n string | symbol | (string | symbol)[]\n > = {};\n\n filters.forEach(filter => {\n if (\n filter instanceof EntityTagFilter ||\n filter instanceof EntityOwnerFilter ||\n filter instanceof EntityLifecycleFilter ||\n filter instanceof EntityNamespaceFilter ||\n filter instanceof EntityUserFilter ||\n filter instanceof EntityOrphanFilter ||\n filter instanceof EntityTextFilter ||\n filter instanceof UserListFilter\n ) {\n return;\n }\n Object.assign(backendCatalogFilters, filter.getCatalogFilters?.() || {});\n });\n\n return backendCatalogFilters;\n}\n\nexport function reduceEntityFilters(\n filters: EntityFilter[],\n): (entity: Entity) => boolean {\n return (entity: Entity) =>\n filters.every(\n filter => !filter.filterEntity || filter.filterEntity(entity),\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 {\n techdocsApiRef,\n techdocsStorageApiRef,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsClient, TechDocsStorageClient } from './client';\nimport {\n rootDocsRouteRef,\n rootRouteRef,\n rootCatalogDocsRouteRef,\n} from './routes';\nimport {\n configApiRef,\n createApiFactory,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport {\n createSearchResultListItemExtension,\n SearchResultListItemExtensionProps,\n} from '@backstage/plugin-search-react';\nimport { TechDocsSearchResultListItemProps } from './search/components/TechDocsSearchResultListItem';\n\n/**\n * The Backstage plugin that renders technical documentation for your components\n *\n * @public\n */\nexport const techdocsPlugin = createPlugin({\n id: 'techdocs',\n apis: [\n createApiFactory({\n api: techdocsStorageApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsStorageClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n createApiFactory({\n api: techdocsApiRef,\n deps: {\n configApi: configApiRef,\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n new TechDocsClient({\n configApi,\n discoveryApi,\n fetchApi,\n }),\n }),\n ],\n routes: {\n root: rootRouteRef,\n docRoot: rootDocsRouteRef,\n entityContent: rootCatalogDocsRouteRef,\n },\n});\n\n/**\n * Routable extension used to render docs\n *\n * @public\n */\nexport const TechdocsPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechdocsPage',\n component: () => import('./Router').then(m => m.Router),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Routable extension used to render docs on Entity page\n *\n * @public\n */\nexport const EntityTechdocsContent = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'EntityTechdocsContent',\n component: () => import('./Router').then(m => m.LegacyEmbeddedDocsRouter),\n mountPoint: rootCatalogDocsRouteRef,\n }),\n);\n\n/**\n * Component which takes a custom tabs config object and renders a documentation landing page.\n *\n * @public\n */\nexport const TechDocsCustomHome = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsCustomHome',\n component: () =>\n import('./home/components/TechDocsCustomHome').then(\n m => m.TechDocsCustomHome,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Responsible for rendering the provided router element\n *\n * @public\n */\nexport const TechDocsIndexPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsIndexPage',\n component: () =>\n import('./home/components/TechDocsIndexPage').then(\n m => m.TechDocsIndexPage,\n ),\n mountPoint: rootRouteRef,\n }),\n);\n\n/**\n * Component responsible for composing a TechDocs reader page experience\n *\n * @public\n */\nexport const TechDocsReaderPage = techdocsPlugin.provide(\n createRoutableExtension({\n name: 'TechDocsReaderPage',\n component: () =>\n import('./reader/components/TechDocsReaderPage').then(\n m => m.TechDocsReaderPage,\n ),\n mountPoint: rootDocsRouteRef,\n }),\n);\n\n/**\n * React extension used to render results on Search page or modal\n *\n * @public\n */\nexport const TechDocsSearchResultListItem: (\n props: SearchResultListItemExtensionProps<TechDocsSearchResultListItemProps>,\n) => JSX.Element | null = techdocsPlugin.provide(\n createSearchResultListItemExtension({\n name: 'TechDocsSearchResultListItem',\n component: () =>\n import('./search/components/TechDocsSearchResultListItem').then(\n m => m.TechDocsSearchResultListItem,\n ),\n predicate: result => result.type === 'techdocs',\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 {\n PluginConfig,\n BackstagePlugin,\n Extension,\n AnyRoutes,\n AnyExternalRoutes,\n PluginFeatureFlagConfig,\n} from './types';\nimport { AnyApiFactory } from '../apis';\n\n/**\n * @internal\n */\nexport class PluginImpl<\n Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> implements BackstagePlugin<Routes, ExternalRoutes>\n{\n constructor(private readonly config: PluginConfig<Routes, ExternalRoutes>) {}\n\n getId(): string {\n return this.config.id;\n }\n\n getApis(): Iterable<AnyApiFactory> {\n return this.config.apis ?? [];\n }\n\n getFeatureFlags(): Iterable<PluginFeatureFlagConfig> {\n return this.config.featureFlags?.slice() ?? [];\n }\n\n get routes(): Routes {\n return this.config.routes ?? ({} as Routes);\n }\n\n get externalRoutes(): ExternalRoutes {\n return this.config.externalRoutes ?? ({} as ExternalRoutes);\n }\n\n provide<T>(extension: Extension<T>): T {\n return extension.expose(this);\n }\n\n toString() {\n return `plugin{${this.config.id}}`;\n }\n}\n\n/**\n * Creates Backstage Plugin from config.\n *\n * @param config - Plugin configuration.\n * @public\n */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n config: PluginConfig<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n return new PluginImpl(config);\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 {\n Entity,\n getCompoundEntityRef,\n parseEntityRef,\n} from '@backstage/catalog-model';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { getEntityRootTechDocsPath } from '@backstage/plugin-techdocs-react';\n\nimport { TechDocsReaderPage } from './plugin';\nimport { TechDocsReaderPageContent } from './reader/components/TechDocsReaderPageContent';\nimport { TechDocsReaderPageSubheader } from './reader/components/TechDocsReaderPageSubheader';\nimport { useEntityPageTechDocsRedirect } from './search/hooks/useTechDocsLocation';\n\ntype EntityPageDocsProps = {\n entity: Entity;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n};\n\nexport const EntityPageDocs = ({\n entity,\n withSearch = true,\n}: EntityPageDocsProps) => {\n let entityRef = getCompoundEntityRef(entity);\n\n const searchResultUrlMapper = useEntityPageTechDocsRedirect(entityRef);\n\n if (entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]) {\n try {\n entityRef = parseEntityRef(\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION],\n );\n } catch {\n // not a fan of this but we don't care if the parseEntityRef fails\n }\n }\n\n const defaultPath = getEntityRootTechDocsPath(entity);\n\n return (\n <TechDocsReaderPage entityRef={entityRef}>\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent\n withSearch={withSearch}\n searchResultUrlMapper={searchResultUrlMapper}\n defaultPath={defaultPath}\n />\n </TechDocsReaderPage>\n );\n};\n","/*\n * Copyright 2024 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 { useMemo } from 'react';\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport { rootCatalogDocsRouteRef, rootDocsRouteRef } from '../../routes';\n\nconst trimStartSlash = (path: string) => path.replace(/^\\/+/, '');\nconst trimEndSlash = (path: string) => path.replace(/\\/+$/, '');\n\n/**\n * Returns a function that takes a location to a Tech Docs entry, and returns a\n * new location, re-routed to the catalog page tab.\n *\n * @internal\n */\nexport function useEntityPageTechDocsRedirect(entityRef: CompoundEntityRef) {\n const { kind, name, namespace } = entityRef;\n\n const routeDocsRoot = useRouteRef(rootDocsRouteRef);\n const routeDocsCatalog = useRouteRef(rootCatalogDocsRouteRef);\n\n // Re-routes a /docs/:namespace/:kind/:name/* location into\n // /catalog/:namespace/:kind/:name/docs/*, while handling situations where\n // these defaults are changed.\n // eslint-disable-next-line react-hooks/rules-of-hooks\n const reRouteLocationToCatalog = useMemo(() => {\n const rootDocsPath = trimEndSlash(routeDocsRoot({ kind, namespace, name }));\n const catalogDocsPath = trimEndSlash(routeDocsCatalog());\n\n return (url: string): string => {\n if (\n url\n .toLocaleLowerCase('en-US')\n .startsWith(rootDocsPath.toLocaleLowerCase('en-US'))\n ) {\n const suffix = trimStartSlash(url.slice(rootDocsPath.length));\n return suffix.length === 0 || suffix.startsWith('#')\n ? `${catalogDocsPath}${suffix}`\n : `${catalogDocsPath}/${suffix}`;\n }\n return url;\n };\n }, [routeDocsRoot, routeDocsCatalog, kind, name, namespace]);\n\n return reRouteLocationToCatalog;\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 Box from '@material-ui/core/Box';\nimport Button from '@material-ui/core/Button';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { CodeSnippet, Link, EmptyState } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n TranslationFunction,\n useTranslationRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { useEntity } from '../../hooks';\nimport { catalogReactTranslationRef } from '../../translation';\n\n/** @public */\nexport type MissingAnnotationEmptyStateClassKey = 'code';\n\nconst useStyles = makeStyles(\n theme => ({\n code: {\n borderRadius: 6,\n margin: theme.spacing(2, 0),\n background:\n theme.palette.type === 'dark' ? '#444' : theme.palette.common.white,\n },\n }),\n { name: 'BackstageMissingAnnotationEmptyState' },\n);\n\nfunction generateYamlExample(\n annotations: string[],\n entity?: Entity,\n): { yamlText: string; lineNumbers: number[] } {\n const kind = entity?.kind || 'Component';\n const name = entity?.metadata.name || 'example';\n const type = entity?.spec?.type || 'website';\n const owner = entity?.spec?.owner || 'user:default/guest';\n\n const yamlText = `apiVersion: backstage.io/v1alpha1\nkind: ${kind}\nmetadata:\n name: ${name}\n annotations:${annotations.map(ann => `\\n ${ann}: value`).join('')}\nspec:\n type: ${type}\n owner: ${owner}`;\n\n let line = 6; // Line 6 is the line number that annotations are added to.\n const lineNumbers: number[] = [];\n annotations.forEach(() => {\n lineNumbers.push(line);\n line++;\n });\n\n return {\n yamlText,\n lineNumbers,\n };\n}\n\nfunction generateDescription(\n annotations: string[],\n entityKind = 'Component',\n t: TranslationFunction<typeof catalogReactTranslationRef.T>,\n) {\n const annotationList = annotations\n .map(ann => <code key={ann}>{ann}</code>)\n .reduce((prev, curr) => (\n <>\n {prev}, {curr}\n </>\n ));\n\n return t('missingAnnotationEmptyState.generateDescription', {\n count: annotations.length,\n entityKind,\n annotations: annotationList,\n });\n}\n\n/**\n * @public\n * Renders an empty state when an annotation is missing from an entity.\n */\nexport function MissingAnnotationEmptyState(props: {\n annotation: string | string[];\n readMoreUrl?: string;\n}) {\n const { t } = useTranslationRef(catalogReactTranslationRef);\n\n let entity: Entity | undefined;\n try {\n const entityContext = useEntity();\n entity = entityContext.entity;\n } catch (err) {\n // ignore when entity context doesnt exist\n }\n\n const { annotation, readMoreUrl } = props;\n const annotations = Array.isArray(annotation) ? annotation : [annotation];\n const url =\n readMoreUrl ||\n 'https://backstage.io/docs/features/software-catalog/well-known-annotations';\n const classes = useStyles();\n\n const entityKind = entity?.kind || 'Component';\n const { yamlText, lineNumbers } = generateYamlExample(annotations, entity);\n return (\n <EmptyState\n missing=\"field\"\n title={t('missingAnnotationEmptyState.title')}\n description={generateDescription(annotations, entityKind, t)}\n action={\n <>\n <Typography variant=\"body1\">\n {t('missingAnnotationEmptyState.annotationYaml', { entityKind })}\n </Typography>\n <Box className={classes.code}>\n <CodeSnippet\n text={yamlText}\n language=\"yaml\"\n showLineNumbers\n highlightedNumbers={lineNumbers}\n customStyle={{ background: 'inherit', fontSize: '115%' }}\n />\n </Box>\n <Button color=\"primary\" component={Link} to={url}>\n {t('missingAnnotationEmptyState.readMore')}\n </Button>\n </>\n }\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 */\n\nimport { ReactElement, PropsWithChildren } from 'react';\nimport { Route, Routes, useRoutes } from 'react-router-dom';\n\nimport { Entity } from '@backstage/catalog-model';\nimport { EntityPageDocs } from './EntityPageDocs';\nimport { TechDocsIndexPage } from './home/components/TechDocsIndexPage';\nimport { TechDocsReaderPage } from './reader/components/TechDocsReaderPage';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport {\n TECHDOCS_ANNOTATION,\n TECHDOCS_EXTERNAL_ANNOTATION,\n} from '@backstage/plugin-techdocs-common';\n\n/**\n * Helper that takes in entity and returns true/false if TechDocs is available for the entity\n *\n * @public\n */\nexport const isTechDocsAvailable = (entity: Entity) =>\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_ANNOTATION]) ||\n Boolean(entity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]);\n\n/**\n * Responsible for registering routes for TechDocs, TechDocs Homepage and separate TechDocs page\n *\n * @public\n */\nexport const Router = () => {\n return (\n <Routes>\n <Route path=\"/\" element={<TechDocsIndexPage />} />\n <Route\n path=\"/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n />\n </Routes>\n );\n};\n\nexport const TechDocsReaderRouter = (props: PropsWithChildren) => {\n const { children } = props;\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '*',\n element: <TechDocsReaderPage />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n return element;\n};\n\nexport const EmbeddedDocsRouter = (\n props: PropsWithChildren<{\n emptyState?: ReactElement;\n withSearch?: boolean;\n }>,\n) => {\n const { children, emptyState, withSearch = true } = props;\n const { entity } = useEntity();\n\n // Using objects instead of <Route> elements, otherwise \"outlet\" will be null on sub-pages and add-ons won't render\n const element = useRoutes([\n {\n path: '/*',\n element: <EntityPageDocs entity={entity} withSearch={withSearch} />,\n children: [\n {\n path: '*',\n element: children,\n },\n ],\n },\n ]);\n\n const projectId =\n entity.metadata.annotations?.[TECHDOCS_ANNOTATION] ||\n entity.metadata.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION];\n\n if (!projectId) {\n return (\n emptyState ?? (\n <MissingAnnotationEmptyState annotation={[TECHDOCS_ANNOTATION]} />\n )\n );\n }\n return element;\n};\n\n/**\n * Responsible for registering route to view docs on Entity page\n *\n * @public\n */\nexport const LegacyEmbeddedDocsRouter = ({\n children,\n withSearch = true,\n}: PropsWithChildren<{ withSearch?: boolean }>) => {\n // Wrap the Router to avoid exposing the emptyState prop in the non-alpha\n // public API and make it easier for us to change later.\n return <EmbeddedDocsRouter children={children} withSearch={withSearch} />;\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 { Config } from '@backstage/config';\n\n// Lower-case entity triplets by default, but allow override.\nexport function toLowerMaybe(str: string, config: Config) {\n return config.getOptionalBoolean(\n 'techdocs.legacyUseCaseSensitiveTripletPaths',\n )\n ? str\n : str.toLocaleLowerCase('en-US');\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 useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\n\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { Entity } from '@backstage/catalog-model';\nimport { rootDocsRouteRef } from '../../../routes';\nimport {\n EmptyState,\n LinkButton,\n Table,\n TableColumn,\n TableOptions,\n TableProps,\n} from '@backstage/core-components';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } from './types';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link DocsTable}.\n *\n * @public\n */\nexport type DocsTableProps = {\n entities: Entity[] | undefined;\n title?: string | undefined;\n loading?: boolean | undefined;\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table documents\n *\n * @public\n */\nexport const DocsTable = (props: DocsTableProps) => {\n const { entities, title, loading, columns, actions, options } = props;\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n if (!entities) return null;\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n const defaultActions: TableProps<DocsTableRow>['actions'] = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\n ];\n\n const pageSize = 20;\n const paging = documents && documents.length > pageSize;\n\n return (\n <>\n {loading || (documents && documents.length > 0) ? (\n <Table<DocsTableRow>\n isLoading={loading}\n options={{\n paging,\n pageSize,\n search: true,\n actionsColumnIndex: -1,\n ...options,\n }}\n data={documents}\n columns={columns || defaultColumns}\n actions={actions || defaultActions}\n title={\n title\n ? `${title} (${documents.length})`\n : `All (${documents.length})`\n }\n />\n ) : (\n <EmptyState\n missing=\"data\"\n title=\"No documents to show\"\n description=\"Create your own document. Check out our Getting Started Information\"\n action={\n <LinkButton\n color=\"primary\"\n to=\"https://backstage.io/docs/features/techdocs/getting-started\"\n variant=\"contained\"\n >\n DOCS\n </LinkButton>\n }\n />\n )}\n </>\n );\n};\n\nDocsTable.columns = columnFactories;\nDocsTable.actions = actionFactories;\n","/*\n * Copyright 2024 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 { useState, useEffect } from 'react';\n\nimport { Table, TableProps } from '@backstage/core-components';\nimport { DocsTableRow } from './types';\nimport {\n EntityTextFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\n\n/**\n * @internal\n */\nexport function OffsetPaginatedDocsTable(props: TableProps<DocsTableRow>) {\n const { actions, columns, data, isLoading, options, title } = props;\n const { updateFilters, setLimit, setOffset, limit, totalItems, offset } =\n useEntityList();\n const [page, setPage] = useState(\n offset && limit ? Math.floor(offset / limit) : 0,\n );\n\n useEffect(() => {\n if (totalItems && page * limit >= totalItems) {\n setOffset!(Math.max(0, totalItems - limit));\n } else {\n setOffset!(Math.max(0, page * limit));\n }\n }, [setOffset, page, limit, totalItems]);\n\n return (\n <Table<DocsTableRow>\n title={title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n pageSizeOptions: [5, 10, 20, 50, 100],\n pageSize: limit,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n ...options,\n }}\n actions={actions}\n onSearchChange={(searchText: string) =>\n updateFilters({\n text: searchText ? new EntityTextFilter(searchText) : undefined,\n })\n }\n page={page}\n onPageChange={newPage => {\n setPage(newPage);\n }}\n onRowsPerPageChange={pageSize => {\n setLimit(pageSize);\n }}\n totalCount={totalItems}\n localization={{ pagination: { labelDisplayedRows: '' } }}\n isLoading={isLoading}\n />\n );\n}\n","/*\n * Copyright 2024 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 { Table, TableProps } from '@backstage/core-components';\nimport { DocsTableRow } from './types';\n\ntype PaginatedDocsTableProps = {\n prev?(): void;\n next?(): void;\n} & TableProps<DocsTableRow>;\n\n/**\n * @internal\n */\n\nexport function CursorPaginatedDocsTable(props: PaginatedDocsTableProps) {\n const {\n actions,\n columns,\n data,\n next,\n prev,\n title,\n isLoading,\n options,\n ...restProps\n } = props;\n\n return (\n <Table\n title={isLoading ? '' : title}\n columns={columns}\n data={data}\n options={{\n paginationPosition: 'both',\n ...options,\n // These settings are configured to force server side pagination\n pageSizeOptions: [],\n showFirstLastPageButtons: false,\n pageSize: Number.MAX_SAFE_INTEGER,\n emptyRowsWhenPaging: false,\n actionsColumnIndex: -1,\n }}\n onPageChange={page => {\n if (page > 0) {\n next?.();\n } else {\n prev?.();\n }\n }}\n /* this will enable the prev button accordingly */\n page={prev ? 1 : 0}\n /* this will enable the next button accordingly */\n totalCount={next ? Number.MAX_VALUE : Number.MAX_SAFE_INTEGER}\n localization={{ pagination: { labelDisplayedRows: '' } }}\n isLoading={isLoading}\n {...restProps}\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 useCopyToClipboard from 'react-use/esm/useCopyToClipboard';\nimport { capitalize } from 'lodash';\nimport {\n CodeSnippet,\n TableColumn,\n TableOptions,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n useEntityList,\n useStarredEntities,\n} from '@backstage/plugin-catalog-react';\nimport { DocsTable } from './DocsTable';\nimport { OffsetPaginatedDocsTable } from './OffsetPaginatedDocsTable';\nimport { CursorPaginatedDocsTable } from './CursorPaginatedDocsTable';\nimport { actionFactories } from './actions';\nimport { columnFactories, defaultColumns } from './columns';\nimport { DocsTableRow } from './types';\nimport { rootDocsRouteRef } from '../../../routes';\nimport { entitiesToDocsMapper } from './helpers';\n\n/**\n * Props for {@link EntityListDocsTable}.\n *\n * @public\n */\nexport type EntityListDocsTableProps = {\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n options?: TableOptions<DocsTableRow>;\n};\n\n/**\n * Component which renders a table with entities from catalog.\n *\n * @public\n */\nexport const EntityListDocsTable = (props: EntityListDocsTableProps) => {\n const { columns, actions, options } = props;\n const { loading, error, entities, filters, paginationMode, pageInfo } =\n useEntityList();\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const [, copyToClipboard] = useCopyToClipboard();\n const getRouteToReaderPageFor = useRouteRef(rootDocsRouteRef);\n const config = useApi(configApiRef);\n\n const title = capitalize(filters.user?.value ?? 'all');\n\n const defaultActions = [\n actionFactories.createCopyDocsUrlAction(copyToClipboard),\n actionFactories.createStarEntityAction(\n isStarredEntity,\n toggleStarredEntity,\n ),\n ];\n\n const documents = entitiesToDocsMapper(\n entities,\n getRouteToReaderPageFor,\n config,\n );\n\n if (paginationMode === 'cursor') {\n return (\n <CursorPaginatedDocsTable\n columns={columns || defaultColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n next={pageInfo?.next}\n prev={pageInfo?.prev}\n />\n );\n } else if (paginationMode === 'offset') {\n return (\n <OffsetPaginatedDocsTable\n columns={columns || defaultColumns}\n isLoading={loading}\n title={title}\n actions={actions || defaultActions}\n options={options}\n data={documents}\n />\n );\n }\n\n if (error) {\n return (\n <WarningPanel\n severity=\"error\"\n title=\"Could not load available documentation.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n );\n }\n\n return (\n <DocsTable\n title={title}\n entities={entities}\n loading={loading}\n actions={actions || defaultActions}\n columns={columns}\n options={options}\n />\n );\n};\n\nEntityListDocsTable.columns = columnFactories;\nEntityListDocsTable.actions = actionFactories;\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 ShareIcon from '@material-ui/icons/Share';\nimport { DocsTableRow } from './types';\nimport { FavoriteToggleIcon } from '@backstage/core-components';\n\n/**\n * Not directly exported, but through DocsTable.actions and EntityListDocsTable.actions\n *\n * @public\n */\nexport const actionFactories = {\n createCopyDocsUrlAction(copyToClipboard: Function) {\n return (row: DocsTableRow) => {\n return {\n icon: () => <ShareIcon fontSize=\"small\" />,\n tooltip: 'Click to copy documentation link to clipboard',\n onClick: () =>\n copyToClipboard(`${window.location.origin}${row.resolved.docsUrl}`),\n };\n };\n },\n createStarEntityAction(\n isStarredEntity: Function,\n toggleStarredEntity: Function,\n ) {\n return (row: DocsTableRow) => {\n const entity = row.entity;\n const isStarred = isStarredEntity(entity);\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => <FavoriteToggleIcon isFavorite={isStarred} />,\n tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',\n onClick: () => toggleStarredEntity(entity),\n };\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 */\n\nimport Box from '@material-ui/core/Box';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { ReactNode } from 'react';\n\nexport type SubvalueCellClassKey = 'value' | 'subvalue';\n\nconst useSubvalueCellStyles = makeStyles(\n theme => ({\n value: {\n marginBottom: theme.spacing(0.75),\n },\n subvalue: {\n color: theme.palette.textSubtle,\n fontWeight: 'normal',\n },\n }),\n { name: 'BackstageSubvalueCell' },\n);\n\ntype SubvalueCellProps = {\n value: ReactNode;\n subvalue: ReactNode;\n};\n\nexport function SubvalueCell(props: SubvalueCellProps) {\n const { value, subvalue } = props;\n const classes = useSubvalueCellStyles();\n\n return (\n <>\n <Box className={classes.value}>{value}</Box>\n <Box className={classes.subvalue}>{subvalue}</Box>\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 { Link, SubvalueCell, TableColumn } from '@backstage/core-components';\nimport { EntityRefLinks } from '@backstage/plugin-catalog-react';\nimport { Entity } from '@backstage/catalog-model';\nimport { DocsTableRow } from './types';\n\nfunction customTitle(entity: Entity): string {\n return entity.metadata.title || entity.metadata.name;\n}\n\n/**\n * Not directly exported, but through DocsTable.columns and EntityListDocsTable.columns\n *\n * @public\n */\nexport const columnFactories = {\n createTitleColumn(options?: { hidden?: boolean }): TableColumn<DocsTableRow> {\n const nameCol = columnFactories.createNameColumn();\n return {\n ...nameCol,\n field: 'entity.metadata.title',\n hidden: options?.hidden,\n };\n },\n createNameColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Document',\n field: 'entity.metadata.name',\n highlight: true,\n searchable: true,\n defaultSort: 'asc',\n customSort: (row1, row2) => {\n const title1 = customTitle(row1.entity).toLocaleLowerCase();\n const title2 = customTitle(row2.entity).toLocaleLowerCase();\n return title1.localeCompare(title2);\n },\n render: (row: DocsTableRow) => (\n <SubvalueCell\n value={\n <Link to={row.resolved.docsUrl}>{customTitle(row.entity)}</Link>\n }\n subvalue={row.entity.metadata.description}\n />\n ),\n };\n },\n createOwnerColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Owner',\n field: 'resolved.ownedByRelationsTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.ownedByRelations}\n defaultKind=\"group\"\n />\n ),\n };\n },\n createKindColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Kind',\n field: 'entity.kind',\n };\n },\n createTypeColumn(): TableColumn<DocsTableRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n };\n },\n};\n\nexport const defaultColumns: TableColumn<DocsTableRow>[] = [\n columnFactories.createTitleColumn({ hidden: true }),\n columnFactories.createNameColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createKindColumn(),\n columnFactories.createTypeColumn(),\n];\n","/*\n * Copyright 2024 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 { RELATION_OWNED_BY, Entity } from '@backstage/catalog-model';\nimport {\n entityPresentationSnapshot,\n getEntityRelations,\n type EntityPresentationApi,\n} from '@backstage/plugin-catalog-react';\nimport { toLowerMaybe } from '../../../helpers';\nimport { ConfigApi, RouteFunc } from '@backstage/core-plugin-api';\n\ntype getRouteFunc = RouteFunc<{\n namespace: string;\n kind: string;\n name: string;\n}>;\n\nexport function entitiesToDocsMapper(\n entities: Entity[],\n getRouteToReaderPageFor: getRouteFunc,\n config: ConfigApi,\n entityPresentationApi?: EntityPresentationApi,\n) {\n return entities.map(entity => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return {\n entity,\n resolved: {\n docsUrl: getRouteToReaderPageFor({\n namespace: toLowerMaybe(\n entity.metadata.namespace ?? 'default',\n config,\n ),\n kind: toLowerMaybe(entity.kind, config),\n name: toLowerMaybe(entity.metadata.name, config),\n }),\n ownedByRelations,\n ownedByRelationsTitle: ownedByRelations\n .map(\n r =>\n entityPresentationSnapshot(\n r,\n { defaultKind: 'group' },\n entityPresentationApi,\n ).primaryTitle,\n )\n .join(', '),\n },\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 { ReactNode, FC } from 'react';\nimport {\n Content,\n ContentHeader,\n SupportButton,\n} from '@backstage/core-components';\nimport {\n CatalogFilterLayout,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport { TechDocsPageWrapper } from './TechDocsPageWrapper';\nimport { TechDocsPicker } from './TechDocsPicker';\nimport { EntityListDocsTable } from './Tables';\nimport { TechDocsIndexPageProps } from './TechDocsIndexPage';\n\n/**\n * Props for {@link DefaultTechDocsHome}\n *\n * @public\n * @deprecated Please use `TechDocsIndexPageProps` instead.\n */\nexport type DefaultTechDocsHomeProps = TechDocsIndexPageProps;\n\n/**\n * Component which renders a default documentation landing page.\n *\n * @public\n */\nexport const DefaultTechDocsHome = (props: TechDocsIndexPageProps) => {\n const {\n initialFilter = 'owned',\n columns,\n actions,\n ownerPickerMode,\n pagination,\n options,\n PageWrapper,\n CustomHeader,\n } = props;\n const Wrapper: FC<{\n children: ReactNode;\n }> = PageWrapper ? PageWrapper : TechDocsPageWrapper;\n const Header: FC =\n CustomHeader ||\n (() => (\n <ContentHeader title=\"\">\n <SupportButton>Discover documentation in your ecosystem.</SupportButton>\n </ContentHeader>\n ));\n return (\n <Wrapper>\n <Content>\n <Header />\n <EntityListProvider pagination={pagination}>\n <CatalogFilterLayout>\n <CatalogFilterLayout.Filters>\n <TechDocsPicker />\n <UserListPicker initialFilter={initialFilter} />\n <EntityOwnerPicker mode={ownerPickerMode} />\n <EntityTagPicker />\n </CatalogFilterLayout.Filters>\n <CatalogFilterLayout.Content>\n <EntityListDocsTable\n actions={actions}\n columns={columns}\n options={options}\n />\n </CatalogFilterLayout.Content>\n </CatalogFilterLayout>\n </EntityListProvider>\n </Content>\n </Wrapper>\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 { FC } from 'react';\nimport { useOutlet } from 'react-router-dom';\nimport {\n TableColumn,\n TableProps,\n TableOptions,\n} from '@backstage/core-components';\nimport {\n EntityListPagination,\n EntityOwnerPickerProps,\n UserListFilterKind,\n} from '@backstage/plugin-catalog-react';\nimport { DefaultTechDocsHome } from './DefaultTechDocsHome';\nimport { DocsTableRow } from './Tables';\n\n/**\n * Props for {@link TechDocsIndexPage}\n *\n * @public\n */\nexport type TechDocsIndexPageProps = {\n initialFilter?: UserListFilterKind;\n columns?: TableColumn<DocsTableRow>[];\n actions?: TableProps<DocsTableRow>['actions'];\n ownerPickerMode?: EntityOwnerPickerProps['mode'];\n pagination?: EntityListPagination;\n options?: TableOptions<DocsTableRow>;\n PageWrapper?: FC;\n CustomHeader?: FC;\n};\n\nexport const TechDocsIndexPage = (props: TechDocsIndexPageProps) => {\n const outlet = useOutlet();\n\n return outlet || <DefaultTechDocsHome {...props} />;\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 { PropsWithChildren, ComponentProps } from 'react';\n\nimport { Header } from '../Header';\nimport { Page } from './Page';\n\ntype PageWithHeaderProps = ComponentProps<typeof Header> & {\n themeId: string;\n};\n\nexport function PageWithHeader(props: PropsWithChildren<PageWithHeaderProps>) {\n const { themeId, children, ...restProps } = props;\n return (\n <Page themeId={themeId}>\n <Header {...restProps} />\n {children}\n </Page>\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 { ReactNode, FC } from 'react';\n\nimport { PageWithHeader } from '@backstage/core-components';\nimport { useApi, configApiRef } from '@backstage/core-plugin-api';\n\n/**\n * Props for {@link TechDocsPageWrapper}\n *\n * @public\n */\nexport type TechDocsPageWrapperProps = {\n children?: ReactNode;\n CustomPageWrapper?: FC<{ children?: ReactNode }>;\n};\n\n/**\n * Component wrapping a TechDocs page with Page and Header components\n *\n * @public\n */\nexport const TechDocsPageWrapper = (props: TechDocsPageWrapperProps) => {\n const { children, CustomPageWrapper } = props;\n const configApi = useApi(configApiRef);\n const generatedSubtitle = `Documentation available in ${\n configApi.getOptionalString('organization.name') ?? 'Backstage'\n }`;\n\n return (\n <>\n {CustomPageWrapper ? (\n <CustomPageWrapper>{children}</CustomPageWrapper>\n ) : (\n <PageWithHeader\n title=\"Documentation\"\n subtitle={generatedSubtitle}\n themeId=\"documentation\"\n >\n {children}\n </PageWithHeader>\n )}\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 { useEffect } from 'react';\nimport {\n CATALOG_FILTER_EXISTS,\n DefaultEntityFilters,\n EntityFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\nimport { TECHDOCS_ANNOTATION } from '@backstage/plugin-techdocs-common';\n\nclass TechDocsFilter implements EntityFilter {\n getCatalogFilters(): Record<string, string | symbol | (string | symbol)[]> {\n return {\n [`metadata.annotations.${TECHDOCS_ANNOTATION}`]: CATALOG_FILTER_EXISTS,\n };\n }\n}\n\ntype CustomFilters = DefaultEntityFilters & {\n techdocs?: TechDocsFilter;\n};\n\n/**\n * Component responsible for updating TechDocs filters\n *\n * @public\n */\nexport const TechDocsPicker = () => {\n const { updateFilters } = useEntityList<CustomFilters>();\n\n useEffect(() => {\n updateFilters({\n techdocs: new TechDocsFilter(),\n });\n }, [updateFilters]);\n\n return null;\n};\n","import _extends from \"@babel/runtime/helpers/esm/extends\";\nimport _objectWithoutProperties from \"@babel/runtime/helpers/esm/objectWithoutProperties\";\nimport * as React from 'react';\nimport clsx from 'clsx';\nimport PropTypes from 'prop-types';\nimport { alpha, withStyles } from '@material-ui/core/styles';\nexport var styles = function styles(theme) {\n return {\n /* Styles applied to the root element. */\n root: {\n display: 'block',\n // Create a \"on paper\" color with sufficient contrast retaining the color\n backgroundColor: alpha(theme.palette.text.primary, theme.palette.type === 'light' ? 0.11 : 0.13),\n height: '1.2em'\n },\n\n /* Styles applied to the root element if `variant=\"text\"`. */\n text: {\n marginTop: 0,\n marginBottom: 0,\n height: 'auto',\n transformOrigin: '0 60%',\n transform: 'scale(1, 0.60)',\n borderRadius: theme.shape.borderRadius,\n '&:empty:before': {\n content: '\"\\\\00a0\"'\n }\n },\n\n /* Styles applied to the root element if `variant=\"rect\"`. */\n rect: {},\n\n /* Styles applied to the root element if `variant=\"circle\"`. */\n circle: {\n borderRadius: '50%'\n },\n\n /* Styles applied to the root element if `animation=\"pulse\"`. */\n pulse: {\n animation: '$pulse 1.5s ease-in-out 0.5s infinite'\n },\n '@keyframes pulse': {\n '0%': {\n opacity: 1\n },\n '50%': {\n opacity: 0.4\n },\n '100%': {\n opacity: 1\n }\n },\n\n /* Styles applied to the root element if `animation=\"wave\"`. */\n wave: {\n position: 'relative',\n overflow: 'hidden',\n '&::after': {\n animation: '$wave 1.6s linear 0.5s infinite',\n background: \"linear-gradient(90deg, transparent, \".concat(theme.palette.action.hover, \", transparent)\"),\n content: '\"\"',\n position: 'absolute',\n transform: 'translateX(-100%)',\n // Avoid flash during server-side hydration\n bottom: 0,\n left: 0,\n right: 0,\n top: 0\n }\n },\n '@keyframes wave': {\n '0%': {\n transform: 'translateX(-100%)'\n },\n '60%': {\n // +0.5s of delay between each loop\n transform: 'translateX(100%)'\n },\n '100%': {\n transform: 'translateX(100%)'\n }\n },\n\n /* Styles applied when the component is passed children. */\n withChildren: {\n '& > *': {\n visibility: 'hidden'\n }\n },\n\n /* Styles applied when the component is passed children and no width. */\n fitContent: {\n maxWidth: 'fit-content'\n },\n\n /* Styles applied when the component is passed children and no height. */\n heightAuto: {\n height: 'auto'\n }\n };\n};\nvar Skeleton = /*#__PURE__*/React.forwardRef(function Skeleton(props, ref) {\n var _props$animation = props.animation,\n animation = _props$animation === void 0 ? 'pulse' : _props$animation,\n classes = props.classes,\n className = props.className,\n _props$component = props.component,\n Component = _props$component === void 0 ? 'span' : _props$component,\n height = props.height,\n _props$variant = props.variant,\n variant = _props$variant === void 0 ? 'text' : _props$variant,\n width = props.width,\n other = _objectWithoutProperties(props, [\"animation\", \"classes\", \"className\", \"component\", \"height\", \"variant\", \"width\"]);\n\n var hasChildren = Boolean(other.children);\n return /*#__PURE__*/React.createElement(Component, _extends({\n ref: ref,\n className: clsx(classes.root, classes[variant], className, hasChildren && [classes.withChildren, !width && classes.fitContent, !height && classes.heightAuto], animation !== false && classes[animation])\n }, other, {\n style: _extends({\n width: width,\n height: height\n }, other.style)\n }));\n});\nprocess.env.NODE_ENV !== \"production\" ? Skeleton.propTypes = {\n /**\n * The animation.\n * If `false` the animation effect is disabled.\n */\n animation: PropTypes.oneOf(['pulse', 'wave', false]),\n\n /**\n * Optional children to infer width and height from.\n */\n children: PropTypes.node,\n\n /**\n * Override or extend the styles applied to the component.\n * See [CSS API](#css) below for more details.\n */\n classes: PropTypes.object.isRequired,\n\n /**\n * @ignore\n */\n className: PropTypes.string,\n\n /**\n * The component used for the root node.\n * Either a string to use a HTML element or a component.\n */\n component: PropTypes\n /* @typescript-to-proptypes-ignore */\n .elementType,\n\n /**\n * Height of the skeleton.\n * Useful when you don't want to adapt the skeleton to a text element but for instance a card.\n */\n height: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),\n\n /**\n * The type of content that will be rendered.\n */\n variant: PropTypes.oneOf(['text', 'rect', 'circle']),\n\n /**\n * Width of the skeleton.\n * Useful when the skeleton is inside an inline element with no width of its own.\n */\n width: PropTypes.oneOfType([PropTypes.number, PropTypes.string])\n} : void 0;\nexport default withStyles(styles, {\n name: 'MuiSkeleton'\n})(Skeleton);","/*\n * Copyright 2022 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 { PropsWithChildren } from 'react';\nimport Helmet from 'react-helmet';\n\nimport Grid from '@material-ui/core/Grid';\nimport Skeleton from '@material-ui/lab/Skeleton';\nimport CodeIcon from '@material-ui/icons/Code';\n\nimport {\n TechDocsAddonLocations as locations,\n TechDocsEntityMetadata,\n TechDocsMetadata,\n} from '@backstage/plugin-techdocs-react';\nimport {\n EntityRefLink,\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { RELATION_OWNED_BY, CompoundEntityRef } from '@backstage/catalog-model';\nimport { Header, HeaderLabel } from '@backstage/core-components';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nimport capitalize from 'lodash/capitalize';\n\nimport { rootRouteRef } from '../../../routes';\nimport { useTechDocsReaderHeaderData } from '../../../hooks/useTechDocsReaderHeaderData';\n\nconst skeleton = <Skeleton animation=\"wave\" variant=\"text\" height={40} />;\n\n/**\n * Props for {@link TechDocsReaderPageHeader}\n *\n * @public\n * @deprecated No need to pass down properties anymore. The component consumes data from `TechDocsReaderPageContext` instead. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom header.\n */\nexport type TechDocsReaderPageHeaderProps = PropsWithChildren<{\n entityRef?: CompoundEntityRef;\n entityMetadata?: TechDocsEntityMetadata;\n techDocsMetadata?: TechDocsMetadata;\n}>;\n\n/**\n * Renders the reader page header.\n * This component does not accept props, please use\n * the Tech Docs add-ons to customize it\n * @public\n */\nexport const TechDocsReaderPageHeader = (\n props: TechDocsReaderPageHeaderProps,\n) => {\n const { children } = props;\n const {\n title,\n subtitle,\n entityRef,\n entityMetadata,\n tabTitle,\n hidden,\n showSourceLink,\n sourceLink,\n addons,\n } = useTechDocsReaderHeaderData();\n\n const docsRootLink = useRouteRef(rootRouteRef)();\n\n if (hidden) return null;\n\n const { spec } = entityMetadata || {};\n const lifecycle = spec?.lifecycle;\n\n const ownedByRelations = entityMetadata\n ? getEntityRelations(entityMetadata, RELATION_OWNED_BY)\n : [];\n\n const labels = (\n <>\n <HeaderLabel\n label={capitalize(entityMetadata?.kind || 'entity')}\n value={\n <EntityRefLink\n color=\"inherit\"\n entityRef={entityRef}\n title={entityMetadata?.metadata.title}\n defaultKind=\"Component\"\n />\n }\n />\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n color=\"inherit\"\n entityRefs={ownedByRelations}\n defaultKind=\"group\"\n />\n }\n />\n )}\n {lifecycle ? (\n <HeaderLabel label=\"Lifecycle\" value={String(lifecycle)} />\n ) : null}\n {showSourceLink ? (\n <HeaderLabel\n label=\"\"\n value={\n <Grid container direction=\"column\" alignItems=\"center\">\n <Grid style={{ padding: 0 }} item>\n <CodeIcon style={{ marginTop: '-25px' }} />\n </Grid>\n <Grid style={{ padding: 0 }} item>\n Source\n </Grid>\n </Grid>\n }\n url={sourceLink}\n />\n ) : null}\n </>\n );\n\n return (\n <Header\n type=\"Documentation\"\n typeLink={docsRootLink}\n title={title || skeleton}\n subtitle={subtitle === '' ? undefined : subtitle || skeleton}\n >\n <Helmet titleTemplate=\"%s\">\n <title>{tabTitle}</title>\n </Helmet>\n {labels}\n {children}\n {addons.renderComponentsByLocation(locations.Header)}\n </Header>\n );\n};\n","/*\n * Copyright 2024 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 { ReactNode } from 'react';\nimport { ErrorPanel } from '@backstage/core-components';\nimport { useApp } from '@backstage/core-plugin-api';\nimport Button from '@material-ui/core/Button';\nimport { useCookieAuthRefresh } from '../../hooks';\n\n/**\n * @public\n * Props for the {@link CookieAuthRefreshProvider} component.\n */\nexport type CookieAuthRefreshProviderProps = {\n // The plugin ID used for discovering the API origin\n pluginId: string;\n // The children to render when the refresh is successful\n children: ReactNode;\n};\n\n/**\n * @public\n * A provider that will refresh the cookie when it is about to expire.\n */\nexport function CookieAuthRefreshProvider(\n props: CookieAuthRefreshProviderProps,\n): JSX.Element {\n const { children, ...options } = props;\n const app = useApp();\n const { Progress } = app.getComponents();\n\n const result = useCookieAuthRefresh(options);\n\n if (result.status === 'loading') {\n return <Progress />;\n }\n\n if (result.status === 'error') {\n return (\n <ErrorPanel error={result.error}>\n <Button variant=\"outlined\" onClick={result.retry}>\n Retry\n </Button>\n </ErrorPanel>\n );\n }\n\n return <>{children}</>;\n}\n","/*\n * Copyright 2024 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 { useEffect, useCallback, useMemo } from 'react';\nimport {\n discoveryApiRef,\n fetchApiRef,\n useApi,\n} from '@backstage/core-plugin-api';\nimport { useAsync, useMountEffect } from '@react-hookz/web';\nimport { ResponseError } from '@backstage/errors';\n\nconst COOKIE_PATH = '/.backstage/auth/v1/cookie';\nconst ONE_YEAR_MS = 365 * 24 * 3600_000;\n\n/**\n * @public\n * A hook that will refresh the cookie when it is about to expire.\n * @param options - Options for configuring the refresh cookie endpoint\n */\nexport function useCookieAuthRefresh(options: {\n // The plugin id used for discovering the API origin\n pluginId: string;\n}):\n | { status: 'loading' }\n | { status: 'error'; error: Error; retry: () => void }\n | { status: 'success'; data: { expiresAt: string } } {\n const { pluginId } = options ?? {};\n const fetchApi = useApi(fetchApiRef);\n const discoveryApi = useApi(discoveryApiRef);\n\n const channel = useMemo(() => {\n return 'BroadcastChannel' in window\n ? new BroadcastChannel(`${pluginId}-auth-cookie-expires-at`)\n : null;\n }, [pluginId]);\n\n const [state, actions] = useAsync<{ expiresAt: string }>(async () => {\n const apiOrigin = await discoveryApi.getBaseUrl(pluginId);\n const requestUrl = `${apiOrigin}${COOKIE_PATH}`;\n const response = await fetchApi.fetch(`${requestUrl}`, {\n credentials: 'include',\n });\n if (!response.ok) {\n // If we get a 404 from the cookie endpoint we assume that it does not\n // exist and cookie auth is not needed. For all active tabs we don't\n // schedule another refresh for the foreseeable future, but new tabs will\n // still check if cookie auth has been added to the deployment.\n // TODO(Rugvip): Once the legacy backend system is no longer supported we should remove this check\n if (response.status === 404) {\n return { expiresAt: new Date(Date.now() + ONE_YEAR_MS) };\n }\n throw await ResponseError.fromResponse(response);\n }\n const data = await response.json();\n if (!data.expiresAt) {\n throw new Error('No expiration date found in response');\n }\n return data;\n });\n\n useMountEffect(actions.execute);\n\n const retry = useCallback(() => {\n actions.execute();\n }, [actions]);\n\n const refresh = useCallback(\n (params: { expiresAt: string }) => {\n // Randomize the refreshing margin with a margin of 1-4 minutes to avoid all tabs refreshing at the same time\n // It cannot be less than 5 minutes otherwise the backend will return the same expiration date\n const margin = (1 + 3 * Math.random()) * 60000;\n const delay = Date.parse(params.expiresAt) - Date.now() - margin;\n const timeout = setTimeout(retry, delay);\n return () => clearTimeout(timeout);\n },\n [retry],\n );\n\n useEffect(() => {\n // Only schedule a refresh if we have a successful response\n if (state.status !== 'success' || !state.result) {\n return () => {};\n }\n channel?.postMessage({\n action: 'COOKIE_REFRESH_SUCCESS',\n payload: state.result,\n });\n let cancel = refresh(state.result);\n const listener = (\n event: MessageEvent<{ action: string; payload: { expiresAt: string } }>,\n ) => {\n const { action, payload } = event.data;\n if (action === 'COOKIE_REFRESH_SUCCESS') {\n cancel();\n cancel = refresh(payload);\n }\n };\n channel?.addEventListener('message', listener);\n return () => {\n cancel();\n channel?.removeEventListener('message', listener);\n };\n }, [state, refresh, channel]);\n\n // Initialising\n if (state.status === 'not-executed') {\n return { status: 'loading' };\n }\n\n // First refresh or retrying without any success before\n // Possible state transitions:\n // e.g. not-executed -> loading (first-refresh)\n // e.g. not-executed -> loading (first-refresh) -> error -> loading (manual-retry)\n if (state.status === 'loading' && !state.result) {\n return { status: 'loading' };\n }\n\n // Retrying after having succeeding at least once\n // Current state is: { status: 'loading', result: {...}, error: undefined | Error }\n // e.g. not-executed -> loading (first-refresh) -> success -> loading (scheduled-refresh) -> error -> loading (manual-retry)\n if (state.status === 'loading' && state.error) {\n return { status: 'loading' };\n }\n\n // Something went wrong during any situation of a refresh\n if (state.status === 'error' && state.error) {\n return { status: 'error', error: state.error, retry };\n }\n\n // At this point it should be safe to assume that we have a successful refresh\n return { status: 'success', data: state.result! };\n}\n","import { useMemo, useRef, useState } from 'react';\nimport { useSyncedRef } from '../useSyncedRef/index.js';\nexport function useAsync(asyncFn, initialValue) {\n const [state, setState] = useState({\n status: 'not-executed',\n error: undefined,\n result: initialValue,\n });\n const promiseRef = useRef();\n const argsRef = useRef();\n const methods = useSyncedRef({\n execute(...params) {\n argsRef.current = params;\n const promise = asyncFn(...params);\n promiseRef.current = promise;\n setState((s) => ({ ...s, status: 'loading' }));\n promise.then((result) => {\n if (promise === promiseRef.current) {\n setState((s) => ({ ...s, status: 'success', error: undefined, result }));\n }\n }, (error) => {\n if (promise === promiseRef.current) {\n setState((s) => ({ ...s, status: 'error', error }));\n }\n });\n return promise;\n },\n reset() {\n setState({\n status: 'not-executed',\n error: undefined,\n result: initialValue,\n });\n promiseRef.current = undefined;\n argsRef.current = undefined;\n },\n });\n return [\n state,\n useMemo(() => ({\n reset() {\n methods.current.reset();\n },\n execute: (...params) => methods.current.execute(...params),\n }), []),\n { promise: promiseRef.current, lastArgs: argsRef.current },\n ];\n}\n","/*\n * Copyright 2022 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 { Children, ReactElement, ReactNode, useMemo } from 'react';\nimport { useOutlet } from 'react-router-dom';\nimport { Page, Progress } from '@backstage/core-components';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport {\n TECHDOCS_ADDONS_KEY,\n TECHDOCS_ADDONS_WRAPPER_KEY,\n TechDocsReaderPageProvider,\n} from '@backstage/plugin-techdocs-react';\nimport { TechDocsReaderPageRenderFunction } from '../../../types';\nimport { TechDocsReaderPageContent } from '../TechDocsReaderPageContent';\nimport { TechDocsReaderPageHeader } from '../TechDocsReaderPageHeader';\nimport { TechDocsReaderPageSubheader } from '../TechDocsReaderPageSubheader';\nimport { rootDocsRouteRef } from '../../../routes';\nimport {\n getComponentData,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport { CookieAuthRefreshProvider } from '@backstage/plugin-auth-react';\nimport {\n createTheme,\n styled,\n ThemeOptions,\n ThemeProvider,\n useTheme,\n} from '@material-ui/core/styles';\nimport { useExternalRedirect } from './useExternalRedirect';\n\n/* An explanation for the multiple ways of customizing the TechDocs reader page\n\nPlease refer to this page on the microsite for the latest recommended approach:\nhttps://backstage.io/docs/features/techdocs/how-to-guides#how-to-customize-the-techdocs-reader-page\n\nThe <TechDocsReaderPage> component is responsible for rendering the <TechDocsReaderPageProvider> and\nits contained version of a <Page>, which in turn renders the <TechDocsReaderPageContent>.\n\nHistorically, there have been different approaches on how this <Page> can be customized, and how the\n<TechDocsReaderPageContent> inside could be exchanged for a custom implementation (which was not\npossible before). Also, the current implementation supports every scenario to avoid breaking default\nconfigurations of TechDocs.\n\nIn particular, there are 4 different TechDocs page configurations:\n\nCONFIGURATION 1: <TechDocsReaderPage> only, no children\n\n<Route path=\"/docs/:namespace/:kind/:name/*\" element={<TechDocsReaderPage />} >\n\nThis is the simplest way to use TechDocs. Only a full page is passed, assuming that it comes with\nits content inside. Since we allowed customizing it, we started providing <TechDocsReaderLayout> as\na default implementation (which contains <TechDocsReaderPageContent>).\n\nCONFIGURATION 2 (not advised): <TechDocsReaderPage> with element children\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={\n <TechDocsReaderPage>\n {techdocsPage}\n </TechDocsReaderPage>\n }\n/>\n\nPreviously, there were two ways of passing children to <TechDocsReaderPage>: either as elements (as\nshown above), or as a render function (described below in CONFIGURATION 3). The \"techdocsPage\" is\nlocated in packages/app/src/components/techdocs and is the default implementation of the content\ninside.\n\nCONFIGURATION 3 (not advised): <TechDocsReaderPage> with render function as child\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={\n <TechDocsReaderPage>\n {({ metadata, entityMetadata, onReady }) => (\n techdocsPage\n )}\n </TechDocsReaderPage>\n }\n/>\n\nSimilar to CONFIGURATION 2, the direct children will be passed to the <TechDocsReaderPage> but in\nthis case interpreted as render prop.\n\nCONFIGURATION 4: <TechDocsReaderPage> and provided content in <Route>\n\n<Route\n path=\"/docs/:namespace/:kind/:name/*\"\n element={<TechDocsReaderPage />}\n>\n {techDocsPage}\n <TechDocsAddons>\n <ExpandableNavigation />\n <ReportIssue />\n <TextSize />\n <LightBox />\n </TechDocsAddons>\n</Route>\n\nThis is the current state in packages/app/src/App.tsx and moved the location of children from inside\nthe element prop in the <Route> to the children of the <Route>. Then, in <TechDocsReaderPage> they\nare retrieved using the useOutlet hook from React Router.\n\nNOTE: Render functions are no longer supported in this approach.\n*/\n\n/**\n * Props for {@link TechDocsReaderLayout}\n * @public\n */\nexport type TechDocsReaderLayoutProps = {\n /**\n * Show or hide the header, defaults to true.\n */\n withHeader?: boolean;\n /**\n * Show or hide the content search bar, defaults to true.\n */\n withSearch?: boolean;\n};\n\n/**\n * Default TechDocs reader page structure composed with a header and content\n * @public\n */\nexport const TechDocsReaderLayout = (props: TechDocsReaderLayoutProps) => {\n const { withSearch, withHeader = true } = props;\n return (\n <Page themeId=\"documentation\">\n {withHeader && <TechDocsReaderPageHeader />}\n <TechDocsReaderPageSubheader />\n <TechDocsReaderPageContent withSearch={withSearch} />\n </Page>\n );\n};\n\n/**\n * @public\n */\nexport type TechDocsReaderPageProps = {\n entityRef?: CompoundEntityRef;\n children?: TechDocsReaderPageRenderFunction | ReactNode;\n overrideThemeOptions?: Partial<ThemeOptions>;\n};\n\n/**\n * Styled Backstage Page that fills available vertical space\n */\nconst StyledPage = styled(Page)({\n height: 'inherit',\n overflowY: 'visible',\n});\n\n/**\n * An addon-aware implementation of the TechDocsReaderPage.\n *\n * @public\n */\nexport const TechDocsReaderPage = (props: TechDocsReaderPageProps) => {\n const currentTheme = useTheme();\n\n const readerPageTheme = useMemo(\n () =>\n createTheme({\n ...currentTheme,\n ...(props.overrideThemeOptions || {}),\n }),\n [currentTheme, props.overrideThemeOptions],\n );\n\n const { kind, name, namespace } = useRouteRefParams(rootDocsRouteRef);\n const { children, entityRef = { kind, name, namespace } } = props;\n\n const outlet = useOutlet();\n\n const memoizedEntityRef = useMemo(\n () => ({\n kind: entityRef.kind,\n name: entityRef.name,\n namespace: entityRef.namespace,\n }),\n [entityRef.kind, entityRef.name, entityRef.namespace],\n );\n\n // Check for external TechDocs redirects and handle navigation\n const { shouldShowProgress } = useExternalRedirect(memoizedEntityRef);\n\n const page: ReactNode = useMemo(() => {\n if (children) {\n return null;\n }\n\n const childrenList = outlet ? Children.toArray(outlet.props.children) : [];\n\n const grandChildren = childrenList.flatMap<ReactElement>(\n child => (child as ReactElement)?.props?.children ?? [],\n );\n\n return grandChildren.find(\n grandChild =>\n !getComponentData(grandChild, TECHDOCS_ADDONS_WRAPPER_KEY) &&\n !getComponentData(grandChild, TECHDOCS_ADDONS_KEY),\n );\n }, [children, outlet]);\n\n // Show full-page loading spinner when checking for external redirects or about to redirect.\n // This replaces the entire page content (header, sidebar, and documentation).\n if (shouldShowProgress) {\n return <Progress />;\n }\n\n // As explained above, \"page\" is configuration 4 and <TechDocsReaderLayout> is 1\n if (!children) {\n return (\n <ThemeProvider theme={readerPageTheme}>\n <CookieAuthRefreshProvider pluginId=\"techdocs\">\n <TechDocsReaderPageProvider entityRef={memoizedEntityRef}>\n {(page as JSX.Element) || <TechDocsReaderLayout />}\n </TechDocsReaderPageProvider>\n </CookieAuthRefreshProvider>\n </ThemeProvider>\n );\n }\n\n // As explained above, a render function is configuration 3 and React element is 2\n return (\n <ThemeProvider theme={readerPageTheme}>\n <CookieAuthRefreshProvider pluginId=\"techdocs\">\n <TechDocsReaderPageProvider entityRef={memoizedEntityRef}>\n {({ metadata, entityMetadata, onReady }) => (\n <StyledPage\n themeId=\"documentation\"\n className=\"techdocs-reader-page\"\n >\n {children instanceof Function\n ? children({\n entityRef: memoizedEntityRef,\n techdocsMetadataValue: metadata.value,\n entityMetadataValue: entityMetadata.value,\n onReady,\n })\n : children}\n </StyledPage>\n )}\n </TechDocsReaderPageProvider>\n </CookieAuthRefreshProvider>\n </ThemeProvider>\n );\n};\n","/*\n * Copyright 2025 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 { useEffect, useRef } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport {\n CompoundEntityRef,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport { buildTechDocsURL } from '@backstage/plugin-techdocs-react';\nimport { TECHDOCS_EXTERNAL_ANNOTATION } from '@backstage/plugin-techdocs-common';\nimport { rootDocsRouteRef } from '../../../routes';\n\n/**\n * Hook to handle external TechDocs redirects based on entity annotations.\n * Checks if an entity has the `backstage.io/techdocs-entity` annotation and\n * redirects to the external TechDocs URL if present.\n *\n * @param entityRef - The entity reference to check for external redirects\n * @returns Object containing loading state and whether a redirect is in progress\n *\n * @internal\n */\nexport function useExternalRedirect(entityRef: CompoundEntityRef): {\n loading: boolean;\n shouldShowProgress: boolean;\n} {\n const catalogApi = useApi(catalogApiRef);\n const navigate = useNavigate();\n const viewTechdocLink = useRouteRef(rootDocsRouteRef);\n\n // Create a stable string key for the entity to use as a dependency.\n // This ensures the useAsync hook only re-runs when the entity changes,\n // preventing redundant API calls during sub-page navigation within the same entity's documentation.\n const entityKey = stringifyEntityRef(entityRef);\n // Track which entity we've already checked to avoid redundant checks\n // when navigating between pages within the same entity's documentation.\n const checkedEntityRef = useRef<string | null>(null);\n const shouldCheckForRedirect = checkedEntityRef.current !== entityKey;\n\n // Check if this entity should redirect to external TechDocs\n const externalRedirectResult = useAsync(async () => {\n try {\n const catalogEntity = await catalogApi.getEntityByRef(entityRef);\n\n if (\n catalogEntity?.metadata?.annotations?.[TECHDOCS_EXTERNAL_ANNOTATION]\n ) {\n return buildTechDocsURL(catalogEntity, viewTechdocLink);\n }\n } catch (error) {\n // Ignore errors and allow the current entity's TechDocs to load.\n // This handles cases where the catalog API is unavailable or the entity doesn't exist.\n }\n\n return undefined;\n }, [entityKey, catalogApi]);\n\n useEffect(() => {\n // Navigate to external TechDocs if a redirect URL is available\n if (!externalRedirectResult.loading && externalRedirectResult.value) {\n navigate(externalRedirectResult.value, { replace: true });\n }\n\n // Mark entity as checked once we've determined there's no redirect needed.\n // This prevents the entire page from unmounting/remounting (showing Progress spinner)\n // on subsequent sub-page navigation within the same entity.\n if (!externalRedirectResult.loading && !externalRedirectResult.value) {\n checkedEntityRef.current = entityKey;\n }\n }, [\n externalRedirectResult.loading,\n externalRedirectResult.value,\n navigate,\n entityKey,\n ]);\n\n // Determine if we should show a loading indicator (which replaces the entire page with a Progress spinner).\n // Only show it when: 1) checking a new/unchecked entity, or 2) we have a redirect URL and are navigating.\n const shouldShowProgress =\n (shouldCheckForRedirect && externalRedirectResult.loading) ||\n !!externalRedirectResult.value;\n\n return {\n loading: externalRedirectResult.loading,\n shouldShowProgress,\n };\n}\n","/*\n * Copyright 2022 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 { ChangeEvent, useCallback, useMemo } from 'react';\n\nimport CircularProgress from '@material-ui/core/CircularProgress';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Autocomplete, {\n AutocompleteProps,\n AutocompleteRenderInputParams,\n} from '@material-ui/lab/Autocomplete';\nimport {\n AutocompleteChangeDetails,\n AutocompleteChangeReason,\n} from '@material-ui/lab/useAutocomplete';\n\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { SearchBar, SearchBarProps } from '../SearchBar';\n\nconst useStyles = makeStyles(theme => ({\n loading: {\n right: theme.spacing(1),\n position: 'absolute',\n },\n}));\n\n/**\n * Props for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteProps<Option> = Omit<\n AutocompleteProps<Option, undefined, undefined, boolean>,\n 'renderInput' | 'disableClearable' | 'multiple'\n> & {\n 'data-testid'?: string;\n inputPlaceholder?: SearchBarProps['placeholder'];\n inputDebounceTime?: SearchBarProps['debounceTime'];\n};\n\n/**\n * Type for {@link SearchAutocomplete}.\n *\n * @public\n */\nexport type SearchAutocompleteComponent = <Option>(\n props: SearchAutocompleteProps<Option>,\n) => JSX.Element;\n\nconst withContext = (\n Component: SearchAutocompleteComponent,\n): SearchAutocompleteComponent => {\n return props => (\n <SearchContextProvider inheritParentContextIfAvailable>\n <Component {...props} />\n </SearchContextProvider>\n );\n};\n\nconst SearchAutocompleteLoadingAdornment = () => {\n const classes = useStyles();\n return (\n <CircularProgress\n className={classes.loading}\n data-testid=\"search-autocomplete-progressbar\"\n color=\"inherit\"\n size={20}\n />\n );\n};\n\n/**\n * Recommended search autocomplete when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchAutocomplete = withContext(\n function SearchAutocompleteComponent<Option>(\n props: SearchAutocompleteProps<Option>,\n ) {\n const {\n loading,\n value,\n onChange = () => {},\n options = [],\n getOptionLabel = (option: Option) => String(option),\n inputPlaceholder,\n inputDebounceTime,\n freeSolo = true,\n fullWidth = true,\n clearOnBlur = false,\n 'data-testid': dataTestId = 'search-autocomplete',\n ...rest\n } = props;\n\n const { setTerm } = useSearch();\n\n const getInputValue = useCallback(\n (option?: null | string | Option) => {\n if (!option) return '';\n if (typeof option === 'string') return option;\n return getOptionLabel(option);\n },\n [getOptionLabel],\n );\n\n const inputValue = useMemo(\n () => getInputValue(value),\n [value, getInputValue],\n );\n\n const handleChange = useCallback(\n (\n event: ChangeEvent<{}>,\n option: null | string | Option,\n reason: AutocompleteChangeReason,\n details?: AutocompleteChangeDetails<Option>,\n ) => {\n setTerm(getInputValue(option));\n onChange(event, option, reason, details);\n },\n [getInputValue, setTerm, onChange],\n );\n\n const renderInput = useCallback(\n ({\n InputProps: { ref, className, endAdornment },\n InputLabelProps,\n ...params\n }: AutocompleteRenderInputParams) => (\n <SearchBar\n {...params}\n ref={ref}\n clearButton={false}\n value={inputValue}\n placeholder={inputPlaceholder}\n debounceTime={inputDebounceTime}\n endAdornment={\n loading ? <SearchAutocompleteLoadingAdornment /> : endAdornment\n }\n InputProps={{ className }}\n />\n ),\n [loading, inputValue, inputPlaceholder, inputDebounceTime],\n );\n\n return (\n <Autocomplete\n {...rest}\n data-testid={dataTestId}\n value={value}\n onChange={handleChange}\n options={options}\n getOptionLabel={getOptionLabel}\n renderInput={renderInput}\n freeSolo={freeSolo}\n fullWidth={fullWidth}\n clearOnBlur={clearOnBlur}\n />\n );\n },\n);\n","/*\n * Copyright 2025 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 { createTranslationRef } from '@backstage/core-plugin-api/alpha';\n\n/**\n * @public\n */\nexport const searchReactTranslationRef = createTranslationRef({\n id: 'search-react',\n messages: {\n searchBar: {\n title: 'Search',\n placeholder: 'Search in {{org}}',\n clearButtonTitle: 'Clear',\n },\n searchFilter: {\n allOptionTitle: 'All',\n },\n searchPagination: {\n limitLabel: 'Results per page:',\n limitText: 'of {{num}}',\n },\n noResultsDescription: 'Sorry, no results were found',\n searchResultGroup: {\n linkTitle: 'See All',\n addFilterButtonTitle: 'Add filter',\n },\n searchResultPager: {\n previous: 'Previous',\n next: 'Next',\n },\n },\n});\n","/*\n * Copyright 2022 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 AnalyticsContext,\n configApiRef,\n useApi,\n useApp,\n} from '@backstage/core-plugin-api';\nimport IconButton from '@material-ui/core/IconButton';\nimport InputAdornment from '@material-ui/core/InputAdornment';\nimport TextField from '@material-ui/core/TextField';\nimport Button from '@material-ui/core/Button';\nimport { TextFieldProps } from '@material-ui/core/TextField';\nimport DefaultSearchIcon from '@material-ui/icons/Search';\nimport {\n ReactNode,\n ChangeEvent,\n forwardRef,\n KeyboardEvent,\n useCallback,\n useEffect,\n useRef,\n useState,\n} from 'react';\nimport useDebounce from 'react-use/esm/useDebounce';\nimport { SearchContextProvider, useSearch } from '../../context';\nimport { useTranslationRef } from '@backstage/frontend-plugin-api';\nimport { searchReactTranslationRef } from '../../translation';\n\n/**\n * Props for {@link SearchBarBase}.\n *\n * @public\n */\nexport type SearchBarBaseProps = Omit<TextFieldProps, 'onChange'> & {\n debounceTime?: number;\n clearButton?: boolean;\n onClear?: () => void;\n onSubmit?: () => void;\n onChange: (value: string) => void;\n endAdornment?: ReactNode;\n};\n\n/**\n * All search boxes exported by the search plugin are based on the <SearchBarBase />,\n * and this one is based on the <InputBase /> component from Material UI.\n * Recommended if you don't use Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBarBase = forwardRef((props: SearchBarBaseProps, ref) => {\n const {\n onChange,\n onKeyDown = () => {},\n onClear = () => {},\n onSubmit = () => {},\n debounceTime = 200,\n clearButton = true,\n fullWidth = true,\n value: defaultValue,\n label,\n placeholder,\n inputProps = {},\n InputProps = {},\n endAdornment,\n ...rest\n } = props;\n\n const configApi = useApi(configApiRef);\n const [value, setValue] = useState<string>('');\n const forwardedValueRef = useRef<string>('');\n const { t } = useTranslationRef(searchReactTranslationRef);\n\n useEffect(() => {\n setValue(prevValue => {\n // We only update the value if our current value is the same as it was\n // for the most recent onChange call. Otherwise it means that the users\n // has continued typing and we should not replace their input.\n if (prevValue === forwardedValueRef.current) {\n return String(defaultValue);\n }\n return prevValue;\n });\n }, [defaultValue, forwardedValueRef]);\n\n useDebounce(\n () => {\n forwardedValueRef.current = value;\n onChange(value);\n },\n debounceTime,\n [value],\n );\n\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>) => {\n setValue(e.target.value);\n },\n [setValue],\n );\n\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLDivElement>) => {\n if (onKeyDown) onKeyDown(e);\n if (onSubmit && e.key === 'Enter') {\n onSubmit();\n }\n },\n [onKeyDown, onSubmit],\n );\n\n const handleClear = useCallback(() => {\n forwardedValueRef.current = '';\n onChange('');\n setValue('');\n if (onClear) {\n onClear();\n }\n }, [onChange, onClear]);\n\n const ariaLabel: string | undefined = label\n ? undefined\n : t('searchBar.title');\n\n const inputPlaceholder =\n placeholder ??\n t('searchBar.placeholder', {\n org: configApi.getOptionalString('app.title') || 'Backstage',\n });\n const SearchIcon = useApp().getSystemIcon('search') || DefaultSearchIcon;\n\n const startAdornment = (\n <InputAdornment position=\"start\">\n <IconButton aria-label=\"Query\" size=\"small\" disabled>\n <SearchIcon />\n </IconButton>\n </InputAdornment>\n );\n\n const clearButtonEndAdornment = (\n <InputAdornment position=\"end\">\n <Button\n aria-label={t('searchBar.clearButtonTitle')}\n size=\"small\"\n onClick={handleClear}\n onKeyDown={event => {\n if (event.key === 'Enter') {\n // write your functionality here\n event.stopPropagation();\n }\n }}\n >\n {t('searchBar.clearButtonTitle')}\n </Button>\n </InputAdornment>\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <TextField\n id=\"search-bar-text-field\"\n data-testid=\"search-bar-next\"\n variant=\"outlined\"\n margin=\"normal\"\n inputRef={ref}\n value={value}\n label={label}\n placeholder={inputPlaceholder}\n InputProps={{\n startAdornment,\n endAdornment: clearButton ? clearButtonEndAdornment : endAdornment,\n ...InputProps,\n }}\n inputProps={{\n 'aria-label': ariaLabel,\n ...inputProps,\n }}\n fullWidth={fullWidth}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n {...rest}\n />\n </SearchContextProvider>\n );\n});\n\n/**\n * Props for {@link SearchBar}.\n *\n * @public\n */\nexport type SearchBarProps = Partial<SearchBarBaseProps>;\n\n/**\n * Recommended search bar when you use the Search Provider or Search Context.\n *\n * @public\n */\nexport const SearchBar = forwardRef((props: SearchBarProps, ref) => {\n const { value: initialValue = '', onChange, ...rest } = props;\n\n const { term, setTerm } = useSearch();\n\n useEffect(() => {\n if (initialValue) {\n setTerm(String(initialValue));\n }\n }, [initialValue, setTerm]);\n\n const handleChange = useCallback(\n (newValue: string) => {\n if (onChange) {\n onChange(newValue);\n } else {\n setTerm(newValue);\n }\n },\n [onChange, setTerm],\n );\n\n return (\n <SearchContextProvider inheritParentContextIfAvailable>\n <AnalyticsContext\n attributes={{ pluginId: 'search', extension: 'SearchBar' }}\n >\n <SearchBarBase\n {...rest}\n ref={ref}\n value={term}\n onChange={handleChange}\n />\n </AnalyticsContext>\n </SearchContextProvider>\n );\n});\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport {\n SearchAutocomplete,\n SearchContextProvider,\n} from '@backstage/plugin-search-react';\nimport { useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport { TechDocsSearchResultListItem } from './TechDocsSearchResultListItem';\nimport {\n useTechDocsSearch,\n TechDocsSearchResult,\n} from '../../hooks/useTechDocsSearch';\n\n/**\n * Props for {@link TechDocsSearch}\n *\n * @public\n */\nexport type TechDocsSearchProps = {\n entityId: CompoundEntityRef;\n entityTitle?: string;\n debounceTime?: number;\n searchResultUrlMapper?: (url: string) => string;\n};\n\nconst isTechDocsSearchResult = (\n option: any,\n): option is TechDocsSearchResult => {\n return option?.document;\n};\n\nconst TechDocsSearchBar = (props: TechDocsSearchProps) => {\n const {\n entityId,\n entityTitle,\n debounceTime = 150,\n searchResultUrlMapper,\n } = props;\n const [open, setOpen] = useState(false);\n const navigate = useNavigate();\n const { results, term, loading } = useTechDocsSearch(entityId);\n\n const handleSelection = (\n _: any,\n selection: TechDocsSearchResult | string | null,\n ) => {\n if (isTechDocsSearchResult(selection)) {\n const { location } = selection.document;\n navigate(\n searchResultUrlMapper ? searchResultUrlMapper(location) : location,\n );\n }\n };\n\n return (\n <SearchAutocomplete\n data-testid=\"techdocs-search-bar\"\n size=\"small\"\n open={open && Boolean(term)}\n getOptionLabel={() => ''}\n filterOptions={x => {\n return x; // This is needed to get renderOption to be called after options change. Bug in material-ui?\n }}\n onClose={() => {\n setOpen(false);\n }}\n onOpen={() => {\n setOpen(true);\n }}\n onChange={handleSelection}\n blurOnSelect\n noOptionsText=\"No results found\"\n value={null}\n options={results}\n renderOption={({ document, highlight }) => (\n <TechDocsSearchResultListItem\n result={document}\n lineClamp={3}\n asListItem={false}\n asLink={false}\n title={document.title}\n highlight={highlight}\n />\n )}\n loading={loading}\n inputDebounceTime={debounceTime}\n inputPlaceholder={`Search ${entityTitle || entityId.name} docs`}\n freeSolo={false}\n />\n );\n};\n\n/**\n * Component used to render search bar on TechDocs page, scoped to\n *\n * @public\n */\nexport const TechDocsSearch = (props: TechDocsSearchProps) => {\n const initialState = {\n term: '',\n types: ['techdocs'],\n pageCursor: '',\n filters: props.entityId,\n };\n return (\n <SearchContextProvider initialState={initialState}>\n <TechDocsSearchBar {...props} />\n </SearchContextProvider>\n );\n};\n","/*\n * Copyright 2022 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 Grid from '@material-ui/core/Grid';\nimport { makeStyles } from '@material-ui/core/styles';\n\nimport { TechDocsShadowDom } from '@backstage/plugin-techdocs-react';\nimport { CompoundEntityRef } from '@backstage/catalog-model';\nimport { Content, Progress } from '@backstage/core-components';\n\nimport { TechDocsSearch } from '../../../search';\nimport { TechDocsStateIndicator } from '../TechDocsStateIndicator';\n\nimport { withTechDocsReaderProvider } from '../TechDocsReaderProvider';\nimport { TechDocsReaderPageContentAddons } from './TechDocsReaderPageContentAddons';\nimport { useTechDocsReaderContentData } from '../../../hooks/useTechDocsReaderContentData';\n\nconst useStyles = makeStyles({\n search: {\n width: '100%',\n '@media (min-width: 76.1875em)': {\n width: 'calc(100% - 34.4rem)',\n margin: '0 auto',\n },\n '@media print': {\n display: 'none',\n },\n },\n});\n\n/**\n * Props for {@link TechDocsReaderPageContent}\n * @public\n */\nexport type TechDocsReaderPageContentProps = {\n /**\n * @deprecated No need to pass down entityRef as property anymore. Consumes the entityName from `TechDocsReaderPageContext`. Use the {@link @backstage/plugin-techdocs-react#useTechDocsReaderPage} hook for custom reader page content.\n */\n entityRef?: CompoundEntityRef;\n /**\n * Path in the docs to render by default. This should be used when rendering docs for an entity that specifies the\n * \"backstage.io/techdocs-entity-path\" annotation for deep linking into another entities docs.\n */\n defaultPath?: string;\n /**\n * Show or hide the search bar, defaults to true.\n */\n withSearch?: boolean;\n /**\n * If {@link TechDocsReaderPageContentProps.withSearch | withSearch} is true,\n * this will redirect the search result urls, e.g. turn search results into\n * links within the \"Docs\" tab of the entity page, instead of the global docs\n * page.\n */\n searchResultUrlMapper?: (url: string) => string;\n /**\n * Callback called when the content is rendered.\n */\n onReady?: () => void;\n};\n\n/**\n * Renders the reader page content\n * @public\n */\nexport const TechDocsReaderPageContent = withTechDocsReaderProvider(\n (props: TechDocsReaderPageContentProps) => {\n const { withSearch = true, searchResultUrlMapper } = props;\n const classes = useStyles();\n\n const {\n entityRef,\n entityMetadata,\n dom,\n handleAppend,\n isNotFound,\n isDomReady,\n showProgress,\n NotFoundErrorPage,\n } = useTechDocsReaderContentData({\n defaultPath: props.defaultPath,\n onReady: props.onReady,\n });\n\n if (isNotFound) return <NotFoundErrorPage />;\n\n if (!isDomReady) {\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n </Grid>\n </Content>\n );\n }\n\n return (\n <Content>\n <Grid container>\n <Grid xs={12} item>\n <TechDocsStateIndicator />\n </Grid>\n {withSearch && (\n <Grid className={classes.search} xs=\"auto\" item>\n <TechDocsSearch\n entityId={entityRef}\n entityTitle={entityMetadata?.metadata?.title}\n searchResultUrlMapper={searchResultUrlMapper}\n />\n </Grid>\n )}\n <Grid xs={12} item>\n {showProgress && <Progress />}\n\n <TechDocsShadowDom element={dom!} onAppend={handleAppend}>\n <TechDocsReaderPageContentAddons />\n </TechDocsShadowDom>\n </Grid>\n </Grid>\n </Content>\n );\n },\n);\n\n/**\n * Props for {@link Reader}\n *\n * @public\n * @deprecated use `TechDocsReaderPageContentProps` instead.\n */\nexport type ReaderProps = TechDocsReaderPageContentProps;\n\n/**\n * Component responsible for rendering TechDocs documentation\n * @public\n * @deprecated use `TechDocsReaderPageContent` component instead.\n */\nexport const Reader = TechDocsReaderPageContent;\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 { PropsWithChildren, ReactNode } from 'react';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Typography from '@material-ui/core/Typography';\nimport { Link } from '@backstage/core-components';\nimport { ResultHighlight } from '@backstage/plugin-search-common';\nimport { HighlightedSearchResultText } from '@backstage/plugin-search-react';\n\nconst useStyles = makeStyles({\n flexContainer: {\n flexWrap: 'wrap',\n },\n itemText: {\n width: '100%',\n marginBottom: '1rem',\n },\n});\n\n/**\n * Props for {@link TechDocsSearchResultListItem}.\n *\n * @public\n */\nexport type TechDocsSearchResultListItemProps = {\n icon?: ReactNode | ((result: any) => ReactNode);\n result?: any;\n highlight?: ResultHighlight;\n rank?: number;\n lineClamp?: number;\n asListItem?: boolean;\n asLink?: boolean;\n title?: string;\n};\n\n/**\n * Component which renders documentation and related metadata.\n *\n * @public\n */\nexport const TechDocsSearchResultListItem = (\n props: TechDocsSearchResultListItemProps,\n) => {\n const {\n result,\n highlight,\n lineClamp = 5,\n asListItem = true,\n asLink = true,\n title,\n icon,\n } = props;\n const classes = useStyles();\n\n const LinkWrapper = ({ children }: PropsWithChildren<{}>) =>\n asLink ? (\n <Link noTrack to={result.location}>\n {children}\n </Link>\n ) : (\n <>{children}</>\n );\n\n const TextItem = () => {\n const resultTitle = highlight?.fields.title ? (\n <HighlightedSearchResultText\n text={highlight.fields.title}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.title\n );\n\n const entityTitle = highlight?.fields.entityTitle ? (\n <HighlightedSearchResultText\n text={highlight.fields.entityTitle}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.entityTitle\n );\n\n const resultName = highlight?.fields.name ? (\n <HighlightedSearchResultText\n text={highlight.fields.name}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.name\n );\n\n if (!result) return null;\n\n return (\n <ListItemText\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n primary={\n <LinkWrapper>\n {title ? (\n title\n ) : (\n <>\n {resultTitle} | {entityTitle ?? resultName} docs\n </>\n )}\n </LinkWrapper>\n }\n secondary={\n <Typography\n component=\"span\"\n style={{\n display: '-webkit-box',\n WebkitBoxOrient: 'vertical',\n WebkitLineClamp: lineClamp,\n overflow: 'hidden',\n }}\n color=\"textSecondary\"\n variant=\"body2\"\n >\n {highlight?.fields.text ? (\n <HighlightedSearchResultText\n text={highlight.fields.text}\n preTag={highlight.preTag}\n postTag={highlight.postTag}\n />\n ) : (\n result.text\n )}\n </Typography>\n }\n />\n );\n };\n\n const ListItemWrapper = ({ children }: PropsWithChildren<{}>) =>\n asListItem ? (\n <>\n {icon && (\n <ListItemIcon>\n {typeof icon === 'function' ? icon(result) : icon}\n </ListItemIcon>\n )}\n <div className={classes.flexContainer}>{children}</div>\n </>\n ) : (\n <>{children}</>\n );\n\n return (\n <ListItemWrapper>\n <TextItem />\n </ListItemWrapper>\n );\n};\n"],"names":["useStyles","makeStyles","EmptyStateImage","missing","classes","missingAnnotation","noInformation","createComponent","noBuild","theme","EmptyState","props","title","description","action","Grid","Typography","FavoriteToggleIcon","isFavorite","StarIcon","UnstarredIcon","FavoriteToggle","id","value","onChange","iconButtonProps","Tooltip","IconButton","createStyles","SvgIcon","BootstrapInput","withStyles","InputBase","SelectComponent","multiple","items","label","placeholder","selected","triggerReset","native","disabled","margin","dataTestId","setValue","useState","isOpen","setOpen","useEffect","Box","FormControl","InputLabel","Select","event","previous","HTMLElement","s","selectedValue","item","el","Chip","CancelIcon","newValue","chip","OpenedDropdown","ClosedDropdown","MenuItem","Checkbox","useFilterStyles","Filters","onChangeFilters","t","useTranslationRef","coreComponentsTranslationRef","selectedFilters","setSelectedFilters","reset","Button","filter","TableLoadingBody","CircularProgress","tableIcons","forwardRef","ref","AddBox","Check","Clear","DeleteOutline","ChevronRight","Edit","SaveAlt","FilterList","FirstPage","LastPage","ChevronLeft","Search","ArrowUpward","Remove","ViewColumn","extractValueByField","data","field","path","i","undefined","StyledMTableHeader","MTableHeader","StyledMTableToolbar","MTableToolbar","useTableStyles","defaultInitialState","TableToolbar","toolbarProps","toolbarRef","setSearch","hasFilters","selectedFiltersLength","toggleFilters","filtersClasses","onSearchChanged","useCallback","searchText","Table","filterConfig","dataValue","columns","emptyContent","options","subtitle","localization","filters","initialState","onStateChange","components","loading","style","restProps","tableClasses","useTheme","calculatedInitialState","filtersOpen","setFiltersOpen","v","search","state","transform","result","key","isEqual","defaultState","getFieldByTitle","titleValue","tableData","useMemo","selectedFiltersArray","Object","filterValue","fieldValue","Array","Toolbar","hasNoRows","columnCount","Body","makeBody","bodyProps","MTableBody","distinctValues","addValue","Set","c","MTable","column","headerStyle","cellStyle","cellStyleFn","rowData","rowColumn","alpha","HeaderLabelContent","className","typographyRootComponent","HeaderLabel","url","contentTypograpyRootComponent","content","Link","entityPresentationSnapshot","entityOrRef","context","entityPresentationApi","stringifyEntityRef","defaultEntityPresentation","BootstrapAutocomplete","Autocomplete","PopperComponent","Popper","TransitionProps","Grow","PaperComponent","Paper","CatalogAutocomplete","name","LabelProps","TextFieldProps","rest","renderInput","params","TextField","merge","autocomplete","ExpandMoreIcon","classNames","CatalogFilterLayout","isScreenSmallerThanBreakpoint","useMediaQuery","filterDrawerOpen","setFilterDrawerOpen","catalogReactTranslationRef","FilterListIcon","Drawer","icon","CheckBoxOutlineBlankIcon","checkedIcon","CheckBoxIcon","OptionCheckbox","EntityAutocompletePickerOption","memo","availableOptions","showCounts","FormControlLabel","EntityAutocompletePicker","Filter","InputProps","initialSelectedOptions","filtersForAvailableValues","hidden","updateFilters","queryParameter","useEntityList","catalogApi","useApi","catalogApiRef","availableValuesFilters","f","availableValues","useAsync","facets","reduceBackendCatalogFilters","Boolean","count","queryParameters","filteredOptions","selectedOptions","setSelectedOptions","shouldAddFilter","newSelectedOptions","String","_event","option","FixedWidthFormControlLabel","_theme","RenderOptionLabel","isGroup","useEntityPresentation","GroupIcon","PersonIcon","EntityOwnerPicker","mode","apis","useApiHolder","entityPresentationApiRef","ownersParameter","text","setText","queryParamOwners","selectedOwners","setSelectedOwners","handleFetch","cache","useFetchEntities","initialSelectedOwnersRefs","isOwnersOnlyMode","queryEntitiesResponse","useAsyncFn","request","limit","cursorRequest","response","initialRequest","facetsEntitiesResponse","useFacetsEntities","enabled","facetsPromise","facet","e","kind","namespace","parseEntityRef","a","b","start","isFacetsResponse","JSON","atob","filteredRefs","entity","normalizedText","end","encodeCursor","entities","payload","btoa","useSelectedOwners","allEntities","useRef","initialSelectedEntities","useMountEffect","entityRef","useDebouncedEffect","availableOwners","EntityOwnerFilter","o","_","owners","x","_e","inputValue","element","hasReachedEnd","Math","EntityTagPicker","EntityTagFilter","UserListPicker","initialFilter","availableFilters","alwaysKeepFilters","configApi","configApiRef","orgName","userParameter","kindParameter","userAndGroupFilterIds","filterGroups","getFilterGroups","SettingsIcon","filterGroup","ownedEntitiesCount","loadingOwnedEntities","ownedEntitiesFilter","useOwnedEntitiesCount","identityApi","identityApiRef","ownershipEntityRefs","loadingEntityRefs","user","allFilters","orderFields","catalogFilters","reduceCatalogFilters","compact","loadingEntityOwnership","fetchEntities","req","ownedClaims","getOwnedCountClaims","ownersRefs","commonOwnedBy","intersection","metadata","totalItems","useDeepCompareEffect","EntityUserFilter","allCount","useAllEntitiesCount","prevRequest","compacted","newRequest","starredEntitiesCount","starredEntitiesFilter","loadingStarredEntities","useStarredEntitiesCount","starredEntities","useStarredEntities","queryParamUserFilter","selectedUserFilter","setSelectedUserFilter","filterCounts","Card","group","Fragment","List","index","ListItemIcon","ListItemText","ListItemSecondaryAction","EntityKindFilter","EntityTypeFilter","values","EntityTextFilter","words","exactMatch","partialMatch","word","m","fullRefs","err","getEntityRelations","RELATION_OWNED_BY","EntityLifecycleFilter","EntityNamespaceFilter","refs","starredEntityRefs","relations","UserListFilter","isOwnedEntity","isStarredEntity","EntityOrphanFilter","orphan","EntityErrorFilter","error","NewEntityListContext","createVersionedContext","OldEntityListContext","createContext","EntityListProvider","isMounted","useMountedState","requestedFilters","setRequestedFilters","location","useLocation","paginationMode","paginationLimit","initialCursor","initialOffset","initialLimit","parsed","qs","queryLimit","Number","isNaN","offset","cursor","setCursor","setOffset","setLimit","outputState","setOutputState","resolvedValue","refresh","kindValue","adjustedFilters","entityFilter","reduceEntityFilters","backendFilter","previousBackendFilter","useDebounce","queryParams","oldParams","newParams","newUrl","window","document","update","prevFilters","newFilters","latestOutput","pageInfo","prevCursor","nextCursor","createVersionedValueMap","versionedHolder","useVersionedContext","oldContext","useContext","Error","getEntityRef","starredEntitiesApi","starredEntitiesApiRef","useObservable","toggleStarredEntity","isEntityTextFilter","isEntityOrderFilter","condensedFilters","compoundFilter","fullTextFilter","backendCatalogFilters","techdocsPlugin","PluginImpl","config","extension","createApiFactory","techdocsStorageApiRef","discoveryApiRef","fetchApiRef","discoveryApi","fetchApi","TechDocsStorageClient","techdocsApiRef","TechDocsClient","rootRouteRef","rootDocsRouteRef","rootCatalogDocsRouteRef","createRoutableExtension","TechDocsReaderPage","createSearchResultListItemExtension","EntityPageDocs","withSearch","getCompoundEntityRef","searchResultUrlMapper","useEntityPageTechDocsRedirect","routeDocsRoot","useRouteRef","routeDocsCatalog","rootDocsPath","catalogDocsPath","suffix","TECHDOCS_EXTERNAL_ANNOTATION","defaultPath","getEntityRootTechDocsPath","TechDocsReaderPageSubheader","TechDocsReaderPageContent","MissingAnnotationEmptyState","type","owner","yamlText","line","lineNumbers","entityContext","useEntity","annotation","readMoreUrl","annotations","entityKind","ann","generateDescription","annotationList","prev","curr","CodeSnippet","Router","Routes","Route","TechDocsIndexPage","TechDocsReaderRouter","children","useRoutes","EmbeddedDocsRouter","emptyState","TECHDOCS_ANNOTATION","LegacyEmbeddedDocsRouter","toLowerMaybe","str","DocsTable","actions","copyToClipboard","useCopyToClipboard","getRouteToReaderPageFor","documents","entitiesToDocsMapper","defaultActions","actionFactories","paging","pageSize","defaultColumns","LinkButton","columnFactories","OffsetPaginatedDocsTable","isLoading","page","setPage","newPage","CursorPaginatedDocsTable","next","EntityListDocsTable","capitalize","WarningPanel","row","ShareIcon","isStarred","useSubvalueCellStyles","SubvalueCell","subvalue","customTitle","row1","row2","title1","title2","resolved","EntityRefLinks","ownedByRelations","r","DefaultTechDocsHome","ownerPickerMode","pagination","PageWrapper","CustomHeader","Wrapper","TechDocsPageWrapper","Header","ContentHeader","SupportButton","Content","TechDocsPicker","outlet","useOutlet","PageWithHeader","themeId","Page","CustomPageWrapper","generatedSubtitle","TechDocsFilter","CATALOG_FILTER_EXISTS","skeleton","Skeleton","TechDocsReaderPageHeader","entityMetadata","tabTitle","showSourceLink","sourceLink","addons","useTechDocsReaderHeaderData","docsRootLink","spec","lifecycle","labels","EntityRefLink","CodeIcon","Helmet","locations","CookieAuthRefreshProvider","Progress","app","useApp","useCookieAuthRefresh","pluginId","channel","BroadcastChannel","apiOrigin","requestUrl","Date","ResponseError","retry","timeout","setTimeout","clearTimeout","cancel","listener","ErrorPanel","TechDocsReaderLayout","withHeader","StyledPage","styled","navigate","viewTechdocLink","entityKey","checkedEntityRef","shouldCheckForRedirect","externalRedirectResult","shouldShowProgress","currentTheme","readerPageTheme","createTheme","useRouteRefParams","memoizedEntityRef","useNavigate","catalogEntity","buildTechDocsURL","grandChildren","childrenList","Children","child","grandChild","getComponentData","TECHDOCS_ADDONS_WRAPPER_KEY","TECHDOCS_ADDONS_KEY","ThemeProvider","TechDocsReaderPageProvider","onReady","Function","Component","searchReactTranslationRef","createTranslationRef","SearchBarBase","onKeyDown","onClear","onSubmit","debounceTime","clearButton","fullWidth","defaultValue","inputProps","endAdornment","forwardedValueRef","prevValue","handleChange","handleKeyDown","handleClear","ariaLabel","inputPlaceholder","SearchIcon","DefaultSearchIcon","startAdornment","InputAdornment","clearButtonEndAdornment","SearchContextProvider","SearchBar","initialValue","term","setTerm","useSearch","AnalyticsContext","SearchAutocompleteLoadingAdornment","SearchAutocomplete","getOptionLabel","inputDebounceTime","freeSolo","clearOnBlur","getInputValue","reason","details","InputLabelProps","TechDocsSearchBar","entityId","entityTitle","open","results","useTechDocsSearch","selection","highlight","TechDocsSearchResultListItem","TechDocsSearch","withTechDocsReaderProvider","dom","handleAppend","isNotFound","isDomReady","showProgress","NotFoundErrorPage","useTechDocsReaderContentData","TechDocsStateIndicator","TechDocsShadowDom","TechDocsReaderPageContentAddons","lineClamp","asListItem","asLink","LinkWrapper","ListItemWrapper","resultTitle","HighlightedSearchResultText","resultName","TextItem"],"mappings":"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"}