@backstage/plugin-catalog 0.7.12-next.0 → 0.7.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 0.7.12
4
+
5
+ ### Patch Changes
6
+
7
+ - f8633307c4: Added an "inspect" entry in the entity three-dots menu, for lower level catalog
8
+ insights and debugging.
9
+ - 9033775d39: Deprecated the `EntityPageLayout`; please use the new extension based `CatalogEntityPage` instead
10
+ - Updated dependencies
11
+ - @backstage/catalog-client@0.6.0
12
+ - @backstage/core-components@0.8.8
13
+ - @backstage/plugin-catalog-react@0.6.14
14
+ - @backstage/integration-react@0.1.21
15
+
3
16
  ## 0.7.12-next.0
4
17
 
5
18
  ### Patch Changes
@@ -1,4 +1,4 @@
1
- export { A as AboutCard, a as AboutContent, b as AboutField } from './index-9e441058.esm.js';
1
+ export { A as AboutCard, a as AboutContent, b as AboutField } from './index-da7631a3.esm.js';
2
2
  import '@backstage/catalog-model';
3
3
  import '@backstage/core-components';
4
4
  import '@backstage/core-plugin-api';
@@ -15,6 +15,7 @@ import '@material-ui/lab';
15
15
  import 'react-router';
16
16
  import '@material-ui/core/styles';
17
17
  import '@material-ui/icons/Cancel';
18
+ import '@material-ui/icons/BugReport';
18
19
  import '@material-ui/icons/MoreVert';
19
20
  import '@backstage/plugin-catalog-common';
20
21
  import '@backstage/errors';
@@ -23,4 +24,4 @@ import 'react-use/lib/useAsync';
23
24
  import 'react-helmet';
24
25
  import '@material-ui/icons/FilterList';
25
26
  import '../components/EntityNotFound/Illo/illo.svg';
26
- //# sourceMappingURL=index-57f985a3.esm.js.map
27
+ //# sourceMappingURL=index-943d86e0.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-943d86e0.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1,4 +1,4 @@
1
- export { C as CatalogPage, D as DefaultCatalogPage } from './index-9e441058.esm.js';
1
+ export { C as CatalogPage, D as DefaultCatalogPage } from './index-da7631a3.esm.js';
2
2
  import '@backstage/catalog-model';
3
3
  import '@backstage/core-components';
4
4
  import '@backstage/core-plugin-api';
@@ -15,6 +15,7 @@ import '@material-ui/lab';
15
15
  import 'react-router';
16
16
  import '@material-ui/core/styles';
17
17
  import '@material-ui/icons/Cancel';
18
+ import '@material-ui/icons/BugReport';
18
19
  import '@material-ui/icons/MoreVert';
19
20
  import '@backstage/plugin-catalog-common';
20
21
  import '@backstage/errors';
@@ -23,4 +24,4 @@ import 'react-use/lib/useAsync';
23
24
  import 'react-helmet';
24
25
  import '@material-ui/icons/FilterList';
25
26
  import '../components/EntityNotFound/Illo/illo.svg';
26
- //# sourceMappingURL=index-a41d9b20.esm.js.map
27
+ //# sourceMappingURL=index-bb9f1736.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-bb9f1736.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -2,7 +2,7 @@ import { RELATION_PART_OF, RELATION_OWNED_BY, ENTITY_DEFAULT_NAMESPACE, LOCATION
2
2
  import { Link, HeaderIconLinkRow, OverflowTooltip, WarningPanel, CodeSnippet, Table, Page, Header, Progress, RoutedTabs, Content, HeaderLabel, ResponseErrorPanel, HeaderTabs, PageWithHeader, ContentHeader, CreateButton, SupportButton } from '@backstage/core-components';
3
3
  import { createExternalRouteRef, useElementFilter, useApi, alertApiRef, useRouteRef, attachComponentData, useApiHolder, configApiRef, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, storageApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
4
4
  import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
5
- import { getEntityRelations, EntityRefLinks, useEntity, catalogApiRef, getEntitySourceLocation, getEntityMetadataEditUrl, useEntityKinds, useEntityListProvider, EntityKindFilter, formatEntityRefTitle, EntityRefLink, useStarredEntities, getEntityMetadataViewUrl, favoriteEntityIcon, favoriteEntityTooltip, useEntityPermission, useEntityCompoundName, EntityContext, UnregisterEntityDialog, FavoriteEntity, catalogRouteRef, EntityListProvider, EntityTypePicker, UserListPicker, EntityOwnerPicker, EntityLifecyclePicker, EntityTagPicker, AsyncEntityProvider, useEntityFromUrl, starredEntitiesApiRef, DefaultStarredEntitiesApi, entityRouteRef } from '@backstage/plugin-catalog-react';
5
+ import { getEntityRelations, EntityRefLinks, useEntity, catalogApiRef, getEntitySourceLocation, getEntityMetadataEditUrl, useEntityKinds, useEntityListProvider, EntityKindFilter, formatEntityRefTitle, EntityRefLink, useStarredEntities, getEntityMetadataViewUrl, favoriteEntityIcon, favoriteEntityTooltip, useEntityPermission, useEntityCompoundName, EntityContext, UnregisterEntityDialog, InspectEntityDialog, FavoriteEntity, catalogRouteRef, EntityListProvider, EntityTypePicker, UserListPicker, EntityOwnerPicker, EntityLifecyclePicker, EntityTagPicker, AsyncEntityProvider, useEntityFromUrl, starredEntitiesApiRef, DefaultStarredEntitiesApi, entityRouteRef } from '@backstage/plugin-catalog-react';
6
6
  import { makeStyles, Typography, Grid, Chip, Card, CardHeader, IconButton, Divider, CardContent, createStyles, capitalize, Select, InputBase, MenuItem, ListItem, ListItemText, Box, ListItemIcon, Popover, MenuList, Dialog, DialogTitle, DialogActions, Button, useMediaQuery, useTheme, Drawer } from '@material-ui/core';
7
7
  import CachedIcon from '@material-ui/icons/Cached';
8
8
  import DocsIcon from '@material-ui/icons/Description';
@@ -11,9 +11,10 @@ import React, { useCallback, useState, useEffect, useMemo, useContext } from 're
11
11
  import OpenInNew from '@material-ui/icons/OpenInNew';
12
12
  import { capitalize as capitalize$1 } from 'lodash';
13
13
  import { Alert } from '@material-ui/lab';
14
- import { useNavigate, useParams, Navigate, matchRoutes, useRoutes, useOutlet, Routes, Route as Route$1 } from 'react-router';
14
+ import { useLocation, useNavigate, useParams, Navigate, matchRoutes, useRoutes, useOutlet, Routes, Route as Route$1 } from 'react-router';
15
15
  import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
16
- import Cancel from '@material-ui/icons/Cancel';
16
+ import CancelIcon from '@material-ui/icons/Cancel';
17
+ import BugReportIcon from '@material-ui/icons/BugReport';
17
18
  import MoreVert from '@material-ui/icons/MoreVert';
18
19
  import { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common';
19
20
  import { assertError } from '@backstage/errors';
@@ -566,7 +567,8 @@ const useStyles$2 = makeStyles$1({
566
567
  const EntityContextMenu = ({
567
568
  UNSTABLE_extraContextMenuItems,
568
569
  UNSTABLE_contextMenuOptions,
569
- onUnregisterEntity
570
+ onUnregisterEntity,
571
+ onInspectEntity
570
572
  }) => {
571
573
  var _a;
572
574
  const [anchorEl, setAnchorEl] = useState();
@@ -614,10 +616,19 @@ const EntityContextMenu = ({
614
616
  onUnregisterEntity();
615
617
  },
616
618
  disabled: disableUnregister
617
- }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(Cancel, {
619
+ }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(CancelIcon, {
618
620
  fontSize: "small"
619
621
  })), /* @__PURE__ */ React.createElement(ListItemText, {
620
622
  primary: "Unregister entity"
623
+ })), /* @__PURE__ */ React.createElement(MenuItem, {
624
+ onClick: () => {
625
+ onClose();
626
+ onInspectEntity();
627
+ }
628
+ }, /* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(BugReportIcon, {
629
+ fontSize: "small"
630
+ })), /* @__PURE__ */ React.createElement(ListItemText, {
631
+ primary: "Inspect entity"
621
632
  })))));
622
633
  };
623
634
 
@@ -683,6 +694,7 @@ const EntityLayout = ({
683
694
  var _a, _b, _c;
684
695
  const { kind, namespace, name } = useEntityCompoundName();
685
696
  const { entity, loading, error } = useContext(EntityContext);
697
+ const location = useLocation();
686
698
  const routes = useElementFilter(children, (elements) => elements.selectByComponentData({
687
699
  key: dataKey,
688
700
  withStrictError: "Child of EntityLayout must be an EntityLayout.Route"
@@ -701,12 +713,17 @@ const EntityLayout = ({
701
713
  }), [entity]);
702
714
  const { headerTitle, headerType } = headerProps$1(kind, namespace, name, entity);
703
715
  const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
716
+ const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false);
704
717
  const navigate = useNavigate();
705
718
  const cleanUpAfterRemoval = async () => {
706
719
  setConfirmationDialogOpen(false);
720
+ setInspectionDialogOpen(false);
707
721
  navigate("/");
708
722
  };
709
- const showRemovalDialog = () => setConfirmationDialogOpen(true);
723
+ useEffect(() => {
724
+ setConfirmationDialogOpen(false);
725
+ setInspectionDialogOpen(false);
726
+ }, [location.pathname]);
710
727
  return /* @__PURE__ */ React.createElement(Page, {
711
728
  themeId: (_c = (_b = (_a = entity == null ? void 0 : entity.spec) == null ? void 0 : _a.type) == null ? void 0 : _b.toString()) != null ? _c : "home"
712
729
  }, /* @__PURE__ */ React.createElement(Header, {
@@ -721,7 +738,8 @@ const EntityLayout = ({
721
738
  }), /* @__PURE__ */ React.createElement(EntityContextMenu, {
722
739
  UNSTABLE_extraContextMenuItems,
723
740
  UNSTABLE_contextMenuOptions,
724
- onUnregisterEntity: showRemovalDialog
741
+ onUnregisterEntity: () => setConfirmationDialogOpen(true),
742
+ onInspectEntity: () => setInspectionDialogOpen(true)
725
743
  }))), loading && /* @__PURE__ */ React.createElement(Progress, null), entity && /* @__PURE__ */ React.createElement(RoutedTabs, {
726
744
  routes
727
745
  }), error && /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Alert, {
@@ -735,6 +753,10 @@ const EntityLayout = ({
735
753
  entity,
736
754
  onConfirm: cleanUpAfterRemoval,
737
755
  onClose: () => setConfirmationDialogOpen(false)
756
+ }), /* @__PURE__ */ React.createElement(InspectEntityDialog, {
757
+ open: inspectionDialogOpen,
758
+ entity,
759
+ onClose: () => setInspectionDialogOpen(false)
738
760
  }));
739
761
  };
740
762
  EntityLayout.Route = Route;
@@ -954,12 +976,12 @@ const EntityPageLayout = ({
954
976
  const { entity, loading, error } = useContext(EntityContext);
955
977
  const { headerTitle, headerType } = headerProps(kind, namespace, name, entity);
956
978
  const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
979
+ const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false);
957
980
  const navigate = useNavigate();
958
981
  const cleanUpAfterRemoval = async () => {
959
982
  setConfirmationDialogOpen(false);
960
983
  navigate("/");
961
984
  };
962
- const showRemovalDialog = () => setConfirmationDialogOpen(true);
963
985
  return /* @__PURE__ */ React.createElement(Page, {
964
986
  themeId: (_c = (_b = (_a = entity == null ? void 0 : entity.spec) == null ? void 0 : _a.type) == null ? void 0 : _b.toString()) != null ? _c : "home"
965
987
  }, /* @__PURE__ */ React.createElement(Header, {
@@ -974,7 +996,8 @@ const EntityPageLayout = ({
974
996
  }), /* @__PURE__ */ React.createElement(EntityContextMenu, {
975
997
  UNSTABLE_extraContextMenuItems,
976
998
  UNSTABLE_contextMenuOptions,
977
- onUnregisterEntity: showRemovalDialog
999
+ onUnregisterEntity: () => setConfirmationDialogOpen(true),
1000
+ onInspectEntity: () => setInspectionDialogOpen(true)
978
1001
  }))), loading && /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(Progress, null)), entity && /* @__PURE__ */ React.createElement(Tabbed.Layout, null, children), error && /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ResponseErrorPanel, {
979
1002
  error
980
1003
  })), !loading && !error && !entity && /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(WarningPanel, {
@@ -986,6 +1009,10 @@ const EntityPageLayout = ({
986
1009
  entity,
987
1010
  onConfirm: cleanUpAfterRemoval,
988
1011
  onClose: () => setConfirmationDialogOpen(false)
1012
+ }), /* @__PURE__ */ React.createElement(InspectEntityDialog, {
1013
+ open: inspectionDialogOpen,
1014
+ entity,
1015
+ onClose: () => setInspectionDialogOpen(false)
989
1016
  }));
990
1017
  };
991
1018
  EntityPageLayout.Content = Tabbed.Content;
@@ -1274,7 +1301,7 @@ const catalogPlugin = createPlugin({
1274
1301
  });
1275
1302
  const CatalogIndexPage = catalogPlugin.provide(createRoutableExtension({
1276
1303
  name: "CatalogIndexPage",
1277
- component: () => import('./index-a41d9b20.esm.js').then((m) => m.CatalogPage),
1304
+ component: () => import('./index-bb9f1736.esm.js').then((m) => m.CatalogPage),
1278
1305
  mountPoint: catalogRouteRef
1279
1306
  }));
1280
1307
  const CatalogEntityPage = catalogPlugin.provide(createRoutableExtension({
@@ -1285,7 +1312,7 @@ const CatalogEntityPage = catalogPlugin.provide(createRoutableExtension({
1285
1312
  const EntityAboutCard = catalogPlugin.provide(createComponentExtension({
1286
1313
  name: "EntityAboutCard",
1287
1314
  component: {
1288
- lazy: () => import('./index-57f985a3.esm.js').then((m) => m.AboutCard)
1315
+ lazy: () => import('./index-943d86e0.esm.js').then((m) => m.AboutCard)
1289
1316
  }
1290
1317
  }));
1291
1318
  const EntityLinksCard = catalogPlugin.provide(createComponentExtension({
@@ -1350,4 +1377,4 @@ const RelatedEntitiesCard = catalogPlugin.provide(createComponentExtension({
1350
1377
  }));
1351
1378
 
1352
1379
  export { AboutCard as A, EntityLayout as B, CatalogPage as C, DefaultCatalogPage as D, EntityAboutCard as E, EntityOrphanWarning as F, isOrphan as G, EntityProcessingErrorsPanel as H, hasCatalogProcessingErrors as I, EntityPageLayout as J, EntitySwitch as K, isKind as L, isNamespace as M, isComponentType as N, FilteredEntityLayout as O, FilterContainer as P, EntityListContainer as Q, Router as R, AboutContent as a, AboutField as b, CatalogClientWrapper as c, CatalogTable as d, CatalogEntityPage as e, CatalogIndexPage as f, catalogPlugin as g, EntityDependencyOfComponentsCard as h, EntityDependsOnComponentsCard as i, EntityDependsOnResourcesCard as j, EntityHasComponentsCard as k, EntityHasResourcesCard as l, EntityHasSubcomponentsCard as m, EntityHasSystemsCard as n, EntityLinksCard as o, EntitySystemDiagramCard as p, RelatedEntitiesCard as q, CatalogKindHeader as r, CatalogResultListItem as s, createNameColumn as t, createSystemColumn as u, createOwnerColumn as v, createSpecTypeColumn as w, createSpecLifecycleColumn as x, createMetadataDescriptionColumn as y, createTagsColumn as z };
1353
- //# sourceMappingURL=index-9e441058.esm.js.map
1380
+ //# sourceMappingURL=index-da7631a3.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-da7631a3.esm.js","sources":["../../src/CatalogClientWrapper.ts","../../src/routes.ts","../../src/components/AboutCard/AboutField.tsx","../../src/components/AboutCard/AboutContent.tsx","../../src/components/AboutCard/AboutCard.tsx","../../src/components/CatalogKindHeader/CatalogKindHeader.tsx","../../src/components/CatalogResultListItem/CatalogResultListItem.tsx","../../src/components/CatalogTable/columns.tsx","../../src/components/CatalogTable/CatalogTable.tsx","../../src/components/EntityContextMenu/EntityContextMenu.tsx","../../src/components/EntityLayout/EntityLayout.tsx","../../src/components/EntityOrphanWarning/DeleteEntityDialog.tsx","../../src/components/EntityOrphanWarning/EntityOrphanWarning.tsx","../../src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx","../../src/components/EntityPageLayout/Tabbed/Tabbed.tsx","../../src/components/EntityPageLayout/EntityPageLayout.tsx","../../src/components/EntitySwitch/EntitySwitch.tsx","../../src/components/EntitySwitch/conditions.ts","../../src/components/FilteredEntityLayout/FilteredEntityLayout.tsx","../../src/components/FilteredEntityLayout/FilterContainer.tsx","../../src/components/FilteredEntityLayout/EntityListContainer.tsx","../../src/components/CatalogPage/DefaultCatalogPage.tsx","../../src/components/CatalogPage/CatalogPage.tsx","../../src/components/EntityNotFound/Illo/Illo.tsx","../../src/components/EntityNotFound/EntityNotFound.tsx","../../src/components/Router.tsx","../../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity, EntityName, Location } from '@backstage/catalog-model';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogClient,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n CatalogEntityAncestorsRequest,\n CatalogEntityAncestorsResponse,\n} from '@backstage/catalog-client';\nimport { IdentityApi } from '@backstage/core-plugin-api';\n\n/**\n * CatalogClient wrapper that injects identity token for all requests\n *\n * @deprecated The default catalog client now uses the `fetchApiRef`\n * implementation, which in turn by default issues tokens just the same as this\n * class used to assist in doing. If you use a custom `fetchApiRef`\n * implementation that does NOT issue tokens, or use a custom `catalogApiRef`\n * implementation which does not use the default `fetchApiRef`, you can wrap\n * your catalog API in this class to get back the old behavior.\n */\nexport class CatalogClientWrapper implements CatalogApi {\n private readonly identityApi: IdentityApi;\n private readonly client: CatalogClient;\n\n constructor(options: { client: CatalogClient; identityApi: IdentityApi }) {\n this.client = options.client;\n this.identityApi = options.identityApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getLocationById(\n id,\n await this.getCredentials(options),\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n return await this.client.getEntities(\n request,\n await this.getCredentials(options),\n );\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return await this.client.getEntityByName(\n compoundName,\n await this.getCredentials(options),\n );\n }\n\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n return await this.client.addLocation(\n request,\n await this.getCredentials(options),\n );\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getOriginLocationByEntity(\n entity,\n await this.getCredentials(options),\n );\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getLocationByEntity(\n entity,\n await this.getCredentials(options),\n );\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.removeLocationById(\n id,\n await this.getCredentials(options),\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.removeEntityByUid(\n uid,\n await this.getCredentials(options),\n );\n }\n\n async refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.refreshEntity(\n entityRef,\n await this.getCredentials(options),\n );\n }\n\n async getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse> {\n return await this.client.getEntityAncestors(\n request,\n await this.getCredentials(options),\n );\n }\n\n private async getCredentials(\n options?: CatalogRequestOptions,\n ): Promise<{ token?: string }> {\n if (options?.token) {\n return { token: options?.token };\n }\n return this.identityApi.getCredentials();\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 { createExternalRouteRef } from '@backstage/core-plugin-api';\n\nexport const createComponentRouteRef = createExternalRouteRef({\n id: 'create-component',\n optional: true,\n});\n\nexport const viewTechDocRouteRef = createExternalRouteRef({\n id: 'view-techdoc',\n optional: true,\n params: ['namespace', 'kind', 'name'],\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 { useElementFilter } from '@backstage/core-plugin-api';\nimport { Grid, makeStyles, Typography } from '@material-ui/core';\nimport React from 'react';\n\nconst useStyles = makeStyles(theme => ({\n value: {\n fontWeight: 'bold',\n overflow: 'hidden',\n lineHeight: '24px',\n wordBreak: 'break-word',\n },\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '10px',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n}));\n\ntype Props = {\n label: string;\n value?: string;\n gridSizes?: Record<string, number>;\n children?: React.ReactNode;\n};\n\nexport const AboutField = ({ label, value, gridSizes, children }: Props) => {\n const classes = useStyles();\n\n const childElements = useElementFilter(children, c => c.getElements());\n\n // Content is either children or a string prop `value`\n const content =\n childElements.length > 0 ? (\n childElements\n ) : (\n <Typography variant=\"body2\" className={classes.value}>\n {value || `unknown`}\n </Typography>\n );\n return (\n <Grid item {...gridSizes}>\n <Typography variant=\"subtitle2\" className={classes.label}>\n {label}\n </Typography>\n {content}\n </Grid>\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 Entity,\n RELATION_OWNED_BY,\n RELATION_PART_OF,\n} from '@backstage/catalog-model';\nimport {\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { Chip, Grid, makeStyles, Typography } from '@material-ui/core';\nimport React from 'react';\nimport { AboutField } from './AboutField';\n\nconst useStyles = makeStyles({\n description: {\n wordBreak: 'break-word',\n },\n});\n\ntype Props = {\n entity: Entity;\n};\n\nexport const AboutContent = ({ entity }: Props) => {\n const classes = useStyles();\n const isSystem = entity.kind.toLocaleLowerCase('en-US') === 'system';\n const isResource = entity.kind.toLocaleLowerCase('en-US') === 'resource';\n const isComponent = entity.kind.toLocaleLowerCase('en-US') === 'component';\n const isAPI = entity.kind.toLocaleLowerCase('en-US') === 'api';\n const isTemplate = entity.kind.toLocaleLowerCase('en-US') === 'template';\n const isLocation = entity.kind.toLocaleLowerCase('en-US') === 'location';\n const isGroup = entity.kind.toLocaleLowerCase('en-US') === 'group';\n\n const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'system',\n });\n const partOfComponentRelations = getEntityRelations(\n entity,\n RELATION_PART_OF,\n {\n kind: 'component',\n },\n );\n const partOfDomainRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'domain',\n });\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n <Grid container>\n <AboutField label=\"Description\" gridSizes={{ xs: 12 }}>\n <Typography variant=\"body2\" paragraph className={classes.description}>\n {entity?.metadata?.description || 'No description'}\n </Typography>\n </AboutField>\n <AboutField\n label=\"Owner\"\n value=\"No Owner\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {ownedByRelations.length > 0 && (\n <EntityRefLinks entityRefs={ownedByRelations} defaultKind=\"group\" />\n )}\n </AboutField>\n {(isSystem || partOfDomainRelations.length > 0) && (\n <AboutField\n label=\"Domain\"\n value=\"No Domain\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {partOfDomainRelations.length > 0 && (\n <EntityRefLinks\n entityRefs={partOfDomainRelations}\n defaultKind=\"domain\"\n />\n )}\n </AboutField>\n )}\n {(isAPI ||\n isComponent ||\n isResource ||\n partOfSystemRelations.length > 0) && (\n <AboutField\n label=\"System\"\n value=\"No System\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {partOfSystemRelations.length > 0 && (\n <EntityRefLinks\n entityRefs={partOfSystemRelations}\n defaultKind=\"system\"\n />\n )}\n </AboutField>\n )}\n {isComponent && partOfComponentRelations.length > 0 && (\n <AboutField\n label=\"Parent Component\"\n value=\"No Parent Component\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n <EntityRefLinks\n entityRefs={partOfComponentRelations}\n defaultKind=\"component\"\n />\n </AboutField>\n )}\n {(isAPI ||\n isComponent ||\n isResource ||\n isTemplate ||\n isGroup ||\n isLocation ||\n typeof entity?.spec?.type === 'string') && (\n <AboutField\n label=\"Type\"\n value={entity?.spec?.type as string}\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n />\n )}\n {(isAPI ||\n isComponent ||\n typeof entity?.spec?.lifecycle === 'string') && (\n <AboutField\n label=\"Lifecycle\"\n value={entity?.spec?.lifecycle as string}\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n />\n )}\n <AboutField\n label=\"Tags\"\n value=\"No Tags\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {(entity?.metadata?.tags || []).map(t => (\n <Chip key={t} size=\"small\" label={t} />\n ))}\n </AboutField>\n </Grid>\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 Entity,\n ENTITY_DEFAULT_NAMESPACE,\n LOCATION_ANNOTATION,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n HeaderIconLinkRow,\n IconLinkVerticalProps,\n InfoCardVariants,\n Link,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n ScmIntegrationIcon,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n catalogApiRef,\n getEntityMetadataEditUrl,\n getEntitySourceLocation,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport {\n Card,\n CardContent,\n CardHeader,\n Divider,\n IconButton,\n makeStyles,\n} from '@material-ui/core';\nimport CachedIcon from '@material-ui/icons/Cached';\nimport DocsIcon from '@material-ui/icons/Description';\nimport EditIcon from '@material-ui/icons/Edit';\nimport React, { useCallback } from 'react';\nimport { viewTechDocRouteRef } from '../../routes';\nimport { AboutContent } from './AboutContent';\n\nconst useStyles = makeStyles({\n gridItemCard: {\n display: 'flex',\n flexDirection: 'column',\n height: 'calc(100% - 10px)', // for pages without content header\n marginBottom: '10px',\n },\n fullHeightCard: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n },\n gridItemCardContent: {\n flex: 1,\n },\n fullHeightCardContent: {\n flex: 1,\n },\n});\n\ntype AboutCardProps = {\n /** @deprecated The entity is now grabbed from context instead */\n entity?: Entity;\n variant?: InfoCardVariants;\n};\n\nexport function AboutCard({ variant }: AboutCardProps) {\n const classes = useStyles();\n const { entity } = useEntity();\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n const catalogApi = useApi(catalogApiRef);\n const alertApi = useApi(alertApiRef);\n const viewTechdocLink = useRouteRef(viewTechDocRouteRef);\n\n const entitySourceLocation = getEntitySourceLocation(\n entity,\n scmIntegrationsApi,\n );\n const entityMetadataEditUrl = getEntityMetadataEditUrl(entity);\n\n const viewInSource: IconLinkVerticalProps = {\n label: 'View Source',\n disabled: !entitySourceLocation,\n icon: <ScmIntegrationIcon type={entitySourceLocation?.integrationType} />,\n href: entitySourceLocation?.locationTargetUrl,\n };\n const viewInTechDocs: IconLinkVerticalProps = {\n label: 'View TechDocs',\n disabled:\n !entity.metadata.annotations?.['backstage.io/techdocs-ref'] ||\n !viewTechdocLink,\n icon: <DocsIcon />,\n href:\n viewTechdocLink &&\n viewTechdocLink({\n namespace: entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE,\n kind: entity.kind,\n name: entity.metadata.name,\n }),\n };\n\n let cardClass = '';\n if (variant === 'gridItem') {\n cardClass = classes.gridItemCard;\n } else if (variant === 'fullHeight') {\n cardClass = classes.fullHeightCard;\n }\n\n let cardContentClass = '';\n if (variant === 'gridItem') {\n cardContentClass = classes.gridItemCardContent;\n } else if (variant === 'fullHeight') {\n cardContentClass = classes.fullHeightCardContent;\n }\n\n const entityLocation = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n // Limiting the ability to manually refresh to the less expensive locations\n const allowRefresh =\n entityLocation?.startsWith('url:') || entityLocation?.startsWith('file:');\n const refreshEntity = useCallback(async () => {\n await catalogApi.refreshEntity(stringifyEntityRef(entity));\n alertApi.post({ message: 'Refresh scheduled', severity: 'info' });\n }, [catalogApi, alertApi, entity]);\n\n return (\n <Card className={cardClass}>\n <CardHeader\n title=\"About\"\n action={\n <>\n {allowRefresh && (\n <IconButton\n aria-label=\"Refresh\"\n title=\"Schedule entity refresh\"\n onClick={refreshEntity}\n >\n <CachedIcon />\n </IconButton>\n )}\n <IconButton\n component={Link}\n aria-label=\"Edit\"\n disabled={!entityMetadataEditUrl}\n title=\"Edit Metadata\"\n to={entityMetadataEditUrl ?? '#'}\n >\n <EditIcon />\n </IconButton>\n </>\n }\n subheader={<HeaderIconLinkRow links={[viewInSource, viewInTechDocs]} />}\n />\n <Divider />\n <CardContent className={cardContentClass}>\n <AboutContent entity={entity} />\n </CardContent>\n </Card>\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, useState } from 'react';\nimport {\n capitalize,\n createStyles,\n InputBase,\n makeStyles,\n MenuItem,\n Select,\n Theme,\n} from '@material-ui/core';\nimport {\n EntityKindFilter,\n useEntityKinds,\n useEntityListProvider,\n} from '@backstage/plugin-catalog-react';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n root: {\n ...theme.typography.h4,\n },\n }),\n);\n\ntype CatalogKindHeaderProps = {\n initialFilter?: string;\n};\n\nexport const CatalogKindHeader = ({\n initialFilter = 'component',\n}: CatalogKindHeaderProps) => {\n const classes = useStyles();\n const { kinds: allKinds = [] } = useEntityKinds();\n const { updateFilters, queryParameters } = useEntityListProvider();\n\n const [selectedKind, setSelectedKind] = useState(\n ([queryParameters.kind].flat()[0] ?? initialFilter).toLocaleLowerCase(\n 'en-US',\n ),\n );\n\n useEffect(() => {\n updateFilters({\n kind: selectedKind ? new EntityKindFilter(selectedKind) : undefined,\n });\n }, [selectedKind, updateFilters]);\n\n // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not\n // be present in allKinds. It should still be shown in the dropdown, but may not have the nice\n // enforced casing from the catalog-backend. This makes a key/value record for the Select options,\n // including selectedKind if it's unknown - but allows the selectedKind to get clobbered by the\n // more proper catalog kind if it exists.\n const options = [capitalize(selectedKind)]\n .concat(allKinds)\n .sort()\n .reduce((acc, kind) => {\n acc[kind.toLocaleLowerCase('en-US')] = kind;\n return acc;\n }, {} as Record<string, string>);\n\n return (\n <Select\n input={<InputBase value={selectedKind} />}\n value={selectedKind}\n onChange={e => setSelectedKind(e.target.value as string)}\n classes={classes}\n >\n {Object.keys(options).map(kind => (\n <MenuItem value={kind} key={kind}>\n {`${options[kind]}s`}\n </MenuItem>\n ))}\n </Select>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Box,\n Chip,\n Divider,\n ListItem,\n ListItemText,\n makeStyles,\n} from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\n\nconst useStyles = makeStyles({\n flexContainer: {\n flexWrap: 'wrap',\n },\n itemText: {\n width: '100%',\n wordBreak: 'break-all',\n marginBottom: '1rem',\n },\n});\n\nexport const CatalogResultListItem = ({ result }: any) => {\n const classes = useStyles();\n return (\n <Link to={result.location}>\n <ListItem alignItems=\"flex-start\" className={classes.flexContainer}>\n <ListItemText\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n primary={result.title}\n secondary={result.text}\n />\n <Box>\n {result.kind && <Chip label={`Kind: ${result.kind}`} size=\"small\" />}\n {result.lifecycle && (\n <Chip label={`Lifecycle: ${result.lifecycle}`} size=\"small\" />\n )}\n </Box>\n </ListItem>\n <Divider component=\"li\" />\n </Link>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport {\n formatEntityRefTitle,\n EntityRefLink,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Chip } from '@material-ui/core';\nimport { EntityRow } from './types';\nimport { OverflowTooltip, TableColumn } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\n\ntype NameColumnProps = {\n defaultKind?: string;\n};\n\nexport function createNameColumn(\n props?: NameColumnProps,\n): TableColumn<EntityRow> {\n function formatContent(entity: Entity): string {\n return (\n entity.metadata?.title ||\n formatEntityRefTitle(entity, {\n defaultKind: props?.defaultKind,\n })\n );\n }\n\n return {\n title: 'Name',\n field: 'resolved.name',\n highlight: true,\n customSort({ entity: entity1 }, { entity: entity2 }) {\n // TODO: We could implement this more efficiently by comparing field by field.\n // This has similar issues as above.\n return formatContent(entity1).localeCompare(formatContent(entity2));\n },\n render: ({ entity }) => (\n <EntityRefLink\n entityRef={entity}\n defaultKind={props?.defaultKind || 'Component'}\n title={entity.metadata?.title}\n />\n ),\n };\n}\n\nexport function createSystemColumn(): TableColumn<EntityRow> {\n return {\n title: 'System',\n field: 'resolved.partOfSystemRelationTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.partOfSystemRelations}\n defaultKind=\"system\"\n />\n ),\n };\n}\n\nexport function createOwnerColumn(): TableColumn<EntityRow> {\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\nexport function createSpecTypeColumn(): TableColumn<EntityRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n hidden: true,\n };\n}\n\nexport function createSpecLifecycleColumn(): TableColumn<EntityRow> {\n return {\n title: 'Lifecycle',\n field: 'entity.spec.lifecycle',\n };\n}\n\nexport function createMetadataDescriptionColumn(): TableColumn<EntityRow> {\n return {\n title: 'Description',\n field: 'entity.metadata.description',\n render: ({ entity }) => (\n <OverflowTooltip\n text={entity.metadata.description}\n placement=\"bottom-start\"\n />\n ),\n width: 'auto',\n };\n}\n\nexport function createTagsColumn(): TableColumn<EntityRow> {\n return {\n title: 'Tags',\n field: 'entity.metadata.tags',\n cellStyle: {\n padding: '0px 16px 0px 20px',\n },\n render: ({ entity }) => (\n <>\n {entity.metadata.tags &&\n entity.metadata.tags.map(t => (\n <Chip\n key={t}\n label={t}\n size=\"small\"\n variant=\"outlined\"\n style={{ marginBottom: '0px' }}\n />\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 */\nimport { RELATION_OWNED_BY, RELATION_PART_OF } from '@backstage/catalog-model';\nimport {\n favoriteEntityIcon,\n favoriteEntityTooltip,\n formatEntityRefTitle,\n getEntityMetadataEditUrl,\n getEntityMetadataViewUrl,\n getEntityRelations,\n useEntityListProvider,\n useStarredEntities,\n} from '@backstage/plugin-catalog-react';\nimport Edit from '@material-ui/icons/Edit';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\nimport { capitalize } from 'lodash';\nimport React, { useMemo } from 'react';\nimport * as columnFactories from './columns';\nimport { EntityRow } from './types';\nimport {\n CodeSnippet,\n Table,\n TableColumn,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\n\ntype CatalogTableProps = {\n columns?: TableColumn<EntityRow>[];\n actions?: TableProps<EntityRow>['actions'];\n};\n\nexport const CatalogTable = ({ columns, actions }: CatalogTableProps) => {\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const { loading, error, entities, filters } = useEntityListProvider();\n\n const defaultColumns: TableColumn<EntityRow>[] = useMemo(\n () => [\n columnFactories.createNameColumn({ defaultKind: filters.kind?.value }),\n columnFactories.createSystemColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createSpecTypeColumn(),\n columnFactories.createSpecLifecycleColumn(),\n columnFactories.createMetadataDescriptionColumn(),\n columnFactories.createTagsColumn(),\n ],\n [filters.kind?.value],\n );\n\n const showTypeColumn = filters.type === undefined;\n // TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar\n const titlePreamble = capitalize(filters.user?.value ?? 'all');\n\n if (error) {\n return (\n <div>\n <WarningPanel\n severity=\"error\"\n title=\"Could not fetch catalog entities.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n </div>\n );\n }\n\n const defaultActions: TableProps<EntityRow>['actions'] = [\n ({ entity }) => {\n const url = getEntityMetadataViewUrl(entity);\n return {\n icon: () => <OpenInNew aria-label=\"View\" fontSize=\"small\" />,\n tooltip: 'View',\n disabled: !url,\n onClick: () => {\n if (!url) return;\n window.open(url, '_blank');\n },\n };\n },\n ({ entity }) => {\n const url = getEntityMetadataEditUrl(entity);\n return {\n icon: () => <Edit aria-label=\"Edit\" fontSize=\"small\" />,\n tooltip: 'Edit',\n disabled: !url,\n onClick: () => {\n if (!url) return;\n window.open(url, '_blank');\n },\n };\n },\n ({ entity }) => {\n const isStarred = isStarredEntity(entity);\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => favoriteEntityIcon(isStarred),\n tooltip: favoriteEntityTooltip(isStarred),\n onClick: () => toggleStarredEntity(entity),\n };\n },\n ];\n\n const rows = entities.map(entity => {\n const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'system',\n });\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return {\n entity,\n resolved: {\n name: formatEntityRefTitle(entity, {\n defaultKind: 'Component',\n }),\n ownedByRelationsTitle: ownedByRelations\n .map(r => formatEntityRefTitle(r, { defaultKind: 'group' }))\n .join(', '),\n ownedByRelations,\n partOfSystemRelationTitle: partOfSystemRelations\n .map(r =>\n formatEntityRefTitle(r, {\n defaultKind: 'system',\n }),\n )\n .join(', '),\n partOfSystemRelations,\n },\n };\n });\n\n const typeColumn = (columns || defaultColumns).find(c => c.title === 'Type');\n if (typeColumn) {\n typeColumn.hidden = !showTypeColumn;\n }\n const showPagination = rows.length > 20;\n\n return (\n <Table<EntityRow>\n isLoading={loading}\n columns={columns || defaultColumns}\n options={{\n paging: showPagination,\n pageSize: 20,\n actionsColumnIndex: -1,\n loadingType: 'linear',\n showEmptyDataSourceMessage: !loading,\n padding: 'dense',\n pageSizeOptions: [20, 50, 100],\n }}\n title={`${titlePreamble} (${entities.length})`}\n data={rows}\n actions={actions || defaultActions}\n />\n );\n};\n\nCatalogTable.columns = columnFactories;\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 Divider,\n IconButton,\n ListItemIcon,\n ListItemText,\n MenuItem,\n MenuList,\n Popover,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport CancelIcon from '@material-ui/icons/Cancel';\nimport BugReportIcon from '@material-ui/icons/BugReport';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport React, { useState } from 'react';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport { useEntityPermission } from '@backstage/plugin-catalog-react';\nimport { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common';\n\n// TODO(freben): It should probably instead be the case that Header sets the theme text color to white inside itself unconditionally instead\nconst useStyles = makeStyles({\n button: {\n color: 'white',\n },\n});\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype Props = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n onUnregisterEntity: () => void;\n onInspectEntity: () => void;\n};\n\nexport const EntityContextMenu = ({\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n onUnregisterEntity,\n onInspectEntity,\n}: Props) => {\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n const classes = useStyles();\n const unregisterPermission = useEntityPermission(\n catalogEntityDeletePermission,\n );\n\n const onOpen = (event: React.SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const onClose = () => {\n setAnchorEl(undefined);\n };\n\n const extraItems = UNSTABLE_extraContextMenuItems && [\n ...UNSTABLE_extraContextMenuItems.map(item => (\n <MenuItem\n key={item.title}\n onClick={() => {\n onClose();\n item.onClick();\n }}\n >\n <ListItemIcon>\n <item.Icon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={item.title} />\n </MenuItem>\n )),\n <Divider key=\"the divider is here!\" />,\n ];\n\n const disableUnregister =\n (!unregisterPermission.allowed ||\n UNSTABLE_contextMenuOptions?.disableUnregister) ??\n false;\n\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={onOpen}\n data-testid=\"menu-button\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={onClose}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n {extraItems}\n <MenuItem\n onClick={() => {\n onClose();\n onUnregisterEntity();\n }}\n disabled={disableUnregister}\n >\n <ListItemIcon>\n <CancelIcon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary=\"Unregister entity\" />\n </MenuItem>\n <MenuItem\n onClick={() => {\n onClose();\n onInspectEntity();\n }}\n >\n <ListItemIcon>\n <BugReportIcon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary=\"Inspect entity\" />\n </MenuItem>\n </MenuList>\n </Popover>\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 {\n Entity,\n ENTITY_DEFAULT_NAMESPACE,\n RELATION_OWNED_BY,\n} from '@backstage/catalog-model';\nimport {\n Content,\n Header,\n HeaderLabel,\n Link,\n Page,\n Progress,\n RoutedTabs,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n attachComponentData,\n IconComponent,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport {\n EntityContext,\n EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n InspectEntityDialog,\n UnregisterEntityDialog,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box, TabProps } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useContext, useEffect, useState } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\n\ntype SubRoute = {\n path: string;\n title: string;\n children: JSX.Element;\n if?: (entity: Entity) => boolean;\n tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;\n};\n\nconst dataKey = 'plugin.catalog.entityLayoutRoute';\n\nconst Route: (props: SubRoute) => null = () => null;\nattachComponentData(Route, dataKey, true);\n\n// This causes all mount points that are discovered within this route to use the path of the route itself\nattachComponentData(Route, 'core.gatherMountPoints', true);\n\nconst EntityLayoutTitle = ({\n entity,\n title,\n}: {\n title: string;\n entity: Entity | undefined;\n}) => {\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n};\n\nconst headerProps = (\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } => {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n return {\n headerTitle: `${name}${\n namespace && namespace !== ENTITY_DEFAULT_NAMESPACE\n ? ` in ${namespace}`\n : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n};\n\nconst EntityLabels = ({ entity }: { entity: Entity }) => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel label=\"Lifecycle\" value={entity.spec.lifecycle} />\n )}\n </>\n );\n};\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype EntityLayoutProps = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n children?: React.ReactNode;\n};\n\n/**\n * EntityLayout is a compound component, which allows you to define a layout for\n * entities using a sub-navigation mechanism.\n *\n * Consists of two parts: EntityLayout and EntityLayout.Route\n *\n * @example\n * ```jsx\n * <EntityLayout>\n * <EntityLayout.Route path=\"/example\" title=\"Example tab\">\n * <div>This is rendered under /example/anything-here route</div>\n * </EntityLayout.Route>\n * </EntityLayout>\n * ```\n */\nexport const EntityLayout = ({\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n children,\n}: EntityLayoutProps) => {\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useContext(EntityContext);\n const location = useLocation();\n const routes = useElementFilter(\n children,\n elements =>\n elements\n .selectByComponentData({\n key: dataKey,\n withStrictError:\n 'Child of EntityLayout must be an EntityLayout.Route',\n })\n .getElements<SubRoute>() // all nodes, element data, maintain structure or not?\n .flatMap(({ props }) => {\n if (props.if && entity && !props.if(entity)) {\n return [];\n }\n\n return [\n {\n path: props.path,\n title: props.title,\n children: props.children,\n tabProps: props.tabProps,\n },\n ];\n }),\n [entity],\n );\n\n const { headerTitle, headerType } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false);\n const navigate = useNavigate();\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n setInspectionDialogOpen(false);\n navigate('/');\n };\n\n // Make sure to close the dialog if the user clicks links in it that navigate\n // to another entity.\n useEffect(() => {\n setConfirmationDialogOpen(false);\n setInspectionDialogOpen(false);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [location.pathname]);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n <Header\n title={<EntityLayoutTitle title={headerTitle} entity={entity!} />}\n pageTitleOverride={headerTitle}\n type={headerType}\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n onUnregisterEntity={() => setConfirmationDialogOpen(true)}\n onInspectEntity={() => setInspectionDialogOpen(true)}\n />\n </>\n )}\n </Header>\n\n {loading && <Progress />}\n\n {entity && <RoutedTabs routes={routes} />}\n\n {error && (\n <Content>\n <Alert severity=\"error\">{error.toString()}</Alert>\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n <WarningPanel title=\"Entity not found\">\n There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n </Content>\n )}\n\n <UnregisterEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\n />\n <InspectEntityDialog\n open={inspectionDialogOpen}\n entity={entity!}\n onClose={() => setInspectionDialogOpen(false)}\n />\n </Page>\n );\n};\n\nEntityLayout.Route = Route;\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 { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { Button, Dialog, DialogActions, DialogTitle } from '@material-ui/core';\nimport React, { useState } from 'react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport { assertError } from '@backstage/errors';\n\ntype Props = {\n open: boolean;\n onClose: () => any;\n onConfirm: () => any;\n entity: Entity;\n};\n\nexport const DeleteEntityDialog = ({\n open,\n onClose,\n onConfirm,\n entity,\n}: Props) => {\n const [busy, setBusy] = useState(false);\n const catalogApi = useApi(catalogApiRef);\n const alertApi = useApi(alertApiRef);\n\n const onDelete = async () => {\n setBusy(true);\n try {\n const uid = entity.metadata.uid;\n await catalogApi.removeEntityByUid(uid!);\n onConfirm();\n } catch (err) {\n assertError(err);\n alertApi.post({ message: err.message });\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose}>\n <DialogTitle id=\"responsive-dialog-title\">\n Are you sure you want to delete this entity?\n </DialogTitle>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n disabled={busy}\n onClick={onDelete}\n >\n Delete\n </Button>\n <Button onClick={onClose} color=\"primary\">\n Cancel\n </Button>\n </DialogActions>\n </Dialog>\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 { catalogRouteRef, useEntity } from '@backstage/plugin-catalog-react';\nimport { Alert } from '@material-ui/lab';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { DeleteEntityDialog } from './DeleteEntityDialog';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nexport const isOrphan = (entity: Entity) =>\n entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true';\n\n/**\n * Displays a warning alert if the entity is marked as orphan with the ability to delete said entity.\n */\nexport const EntityOrphanWarning = () => {\n const navigate = useNavigate();\n const catalogLink = useRouteRef(catalogRouteRef);\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const { entity } = useEntity();\n\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n navigate(catalogLink());\n };\n\n return (\n <>\n <Alert severity=\"warning\" onClick={() => setConfirmationDialogOpen(true)}>\n This entity is not referenced by any location and is therefore not\n receiving updates. Click here to delete.\n </Alert>\n <DeleteEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\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 {\n Entity,\n AlphaEntity,\n stringifyEntityRef,\n EntityStatusItem,\n compareEntityToRef,\n} from '@backstage/catalog-model';\nimport {\n catalogApiRef,\n EntityRefLink,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport { Box } from '@material-ui/core';\nimport React from 'react';\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport {\n CatalogApi,\n ENTITY_STATUS_CATALOG_PROCESSING_TYPE,\n} from '@backstage/catalog-client';\nimport { useApi, ApiHolder } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { SerializedError } from '@backstage/errors';\n\nconst errorFilter = (i: EntityStatusItem) =>\n i.error &&\n i.level === 'error' &&\n i.type === ENTITY_STATUS_CATALOG_PROCESSING_TYPE;\n\ntype GetOwnAndAncestorsErrorsResponse = {\n items: {\n errors: SerializedError[];\n entity: Entity;\n }[];\n};\n\nasync function getOwnAndAncestorsErrors(\n entityRef: string,\n catalogApi: CatalogApi,\n): Promise<GetOwnAndAncestorsErrorsResponse> {\n const ancestors = await catalogApi.getEntityAncestors({ entityRef });\n const items = ancestors.items\n .map(item => {\n const statuses = (item.entity as AlphaEntity).status?.items ?? [];\n const errors = statuses\n .filter(errorFilter)\n .map(e => e.error)\n .filter((e): e is SerializedError => Boolean(e));\n return { errors: errors, entity: item.entity };\n })\n .filter(item => item.errors.length > 0);\n return { items };\n}\n\nexport const hasCatalogProcessingErrors = async (\n entity: Entity,\n context: { apis: ApiHolder },\n) => {\n const catalogApi = context.apis.get(catalogApiRef);\n if (!catalogApi) {\n throw new Error(`No implementation available for ${catalogApiRef}`);\n }\n\n const errors = await getOwnAndAncestorsErrors(\n stringifyEntityRef(entity),\n catalogApi,\n );\n return errors.items.length > 0;\n};\n\n/**\n * Displays a list of errors from the ancestors of the current entity.\n */\nexport const EntityProcessingErrorsPanel = () => {\n const { entity } = useEntity();\n const entityRef = stringifyEntityRef(entity);\n const catalogApi = useApi(catalogApiRef);\n const { loading, error, value } = useAsync(async () => {\n return getOwnAndAncestorsErrors(entityRef, catalogApi);\n }, [entityRef, catalogApi]);\n\n if (error) {\n return (\n <Box mb={1}>\n <ResponseErrorPanel error={error} />\n </Box>\n );\n }\n\n if (loading || !value) {\n return null;\n }\n\n return (\n <>\n {value.items.map((ancestorError, index) => (\n <Box key={index} mb={1}>\n {!compareEntityToRef(\n entity,\n stringifyEntityRef(ancestorError.entity),\n ) && (\n <Box p={1}>\n The error below originates from{' '}\n <EntityRefLink entityRef={ancestorError.entity} />\n </Box>\n )}\n {ancestorError.errors.map((e, i) => (\n <ResponseErrorPanel key={i} error={e} />\n ))}\n </Box>\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 */\nimport React from 'react';\nimport {\n useParams,\n useNavigate,\n PartialRouteObject,\n matchRoutes,\n RouteObject,\n useRoutes,\n Navigate,\n RouteMatch,\n} from 'react-router';\nimport { Helmet } from 'react-helmet';\nimport { Tab, HeaderTabs, Content } from '@backstage/core-components';\n\nconst getSelectedIndexOrDefault = (\n matchedRoute: RouteMatch,\n tabs: Tab[],\n defaultIndex = 0,\n) => {\n if (!matchedRoute) return defaultIndex;\n const tabIndex = tabs.findIndex(t => t.id === matchedRoute.route.path);\n return ~tabIndex ? tabIndex : defaultIndex;\n};\n\n/**\n * Compound component, which allows you to define layout\n * for EntityPage using Tabs as a sub-navigation mechanism\n * Consists of 2 parts: Tabbed.Layout and Tabbed.Content.\n * Takes care of: tabs, routes, document titles, spacing around content\n *\n * @example\n * ```jsx\n * <Tabbed.Layout>\n * <Tabbed.Content\n * title=\"Example tab\"\n * route=\"/example/*\"\n * element={<div>This is rendered under /example/anything-here route</div>}\n * />\n * </TabbedLayout>\n * ```\n */\nexport const Tabbed = {\n Layout: ({ children }: { children: React.ReactNode }) => {\n const routes: PartialRouteObject[] = [];\n const tabs: Tab[] = [];\n const params = useParams();\n const navigate = useNavigate();\n\n React.Children.forEach(children, child => {\n if (!React.isValidElement(child)) {\n // Skip conditionals resolved to falses/nulls/undefineds etc\n return;\n }\n if (child.type !== Tabbed.Content) {\n throw new Error(\n 'This component only accepts Content elements as direct children. Check the code of the EntityPage.',\n );\n }\n const pathAndId = (child as JSX.Element).props.path;\n\n // Child here must be then always a functional component without any wrappers\n tabs.push({\n id: pathAndId,\n label: (child as JSX.Element).props.title,\n });\n\n routes.push({\n path: pathAndId,\n element: child.props.element,\n });\n });\n\n // Add catch-all for incorrect sub-routes\n if ((routes?.[0]?.path ?? '') !== '')\n routes.push({\n path: '/*',\n element: <Navigate to={routes[0].path!} />,\n });\n\n const [matchedRoute] =\n matchRoutes(routes as RouteObject[], `/${params['*']}`) ?? [];\n const selectedIndex = getSelectedIndexOrDefault(matchedRoute, tabs);\n const currentTab = tabs[selectedIndex];\n const title = currentTab?.label;\n\n const onTabChange = (index: number) =>\n // Remove trailing /*\n // And remove leading / for relative navigation\n // Note! route resolves relative to the position in the React tree,\n // not relative to current location\n navigate(tabs[index].id.replace(/\\/\\*$/, '').replace(/^\\//, ''));\n\n const currentRouteElement = useRoutes(routes);\n\n if (!currentTab) return null;\n return (\n <>\n <HeaderTabs\n tabs={tabs}\n selectedIndex={selectedIndex}\n onChange={onTabChange}\n />\n <Content>\n <Helmet title={title} />\n {currentRouteElement}\n </Content>\n </>\n );\n },\n Content: (_props: { path: string; title: string; element: JSX.Element }) =>\n null,\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 {\n Entity,\n ENTITY_DEFAULT_NAMESPACE,\n RELATION_OWNED_BY,\n} from '@backstage/catalog-model';\nimport {\n EntityContext,\n EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n InspectEntityDialog,\n UnregisterEntityDialog,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box } from '@material-ui/core';\nimport React, { useContext, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\nimport { Tabbed } from './Tabbed';\n\nimport {\n Content,\n Header,\n HeaderLabel,\n Link,\n Page,\n Progress,\n ResponseErrorPanel,\n WarningPanel,\n} from '@backstage/core-components';\n\nimport { IconComponent } from '@backstage/core-plugin-api';\n\nconst EntityPageTitle = ({\n entity,\n title,\n}: {\n title: string;\n entity: Entity | undefined;\n}) => (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\">\n {title}\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n);\n\nconst EntityLabels = ({ entity }: { entity: Entity }) => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel label=\"Lifecycle\" value={entity.spec.lifecycle} />\n )}\n </>\n );\n};\n\nconst headerProps = (\n kind: string,\n namespace: string | undefined,\n name: string,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } => {\n return {\n headerTitle: `${name}${\n namespace && namespace !== ENTITY_DEFAULT_NAMESPACE\n ? ` in ${namespace}`\n : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n};\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype EntityPageLayoutProps = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n children?: React.ReactNode;\n};\n\n/**\n * Old entity page, only used by the old router based hierarchies.\n *\n * @deprecated Please use CatalogEntityPage instead\n */\nexport const EntityPageLayout = ({\n children,\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n}: EntityPageLayoutProps) => {\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useContext(EntityContext);\n const { headerTitle, headerType } = headerProps(\n kind,\n namespace,\n name,\n entity!,\n );\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const [inspectionDialogOpen, setInspectionDialogOpen] = useState(false);\n const navigate = useNavigate();\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n navigate('/');\n };\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n <Header\n title={<EntityPageTitle title={headerTitle} entity={entity!} />}\n pageTitleOverride={headerTitle}\n type={headerType}\n >\n {/* TODO: Make entity labels configurable for entity kind / type */}\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n onUnregisterEntity={() => setConfirmationDialogOpen(true)}\n onInspectEntity={() => setInspectionDialogOpen(true)}\n />\n </>\n )}\n </Header>\n\n {loading && (\n <Content>\n <Progress />\n </Content>\n )}\n\n {entity && <Tabbed.Layout>{children}</Tabbed.Layout>}\n\n {error && (\n <Content>\n <ResponseErrorPanel error={error} />\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n <WarningPanel title=\"Entity not found\">\n There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n </Content>\n )}\n\n <UnregisterEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\n />\n <InspectEntityDialog\n open={inspectionDialogOpen}\n entity={entity!}\n onClose={() => setInspectionDialogOpen(false)}\n />\n </Page>\n );\n};\n\nEntityPageLayout.Content = Tabbed.Content;\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 { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport React, { PropsWithChildren, ReactNode } from 'react';\nimport {\n attachComponentData,\n useApiHolder,\n useElementFilter,\n ApiHolder,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\n\nconst ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch';\n\nconst EntitySwitchCase = (_: {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: ReactNode;\n}) => null;\n\nattachComponentData(EntitySwitchCase, ENTITY_SWITCH_KEY, true);\n\ntype SwitchCase = {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: JSX.Element;\n};\n\ntype SwitchCaseResult = {\n if: boolean | Promise<boolean>;\n children: JSX.Element;\n};\n\nexport const EntitySwitch = ({ children }: PropsWithChildren<{}>) => {\n const { entity } = useEntity();\n const apis = useApiHolder();\n const results = useElementFilter(\n children,\n collection =>\n collection\n .selectByComponentData({\n key: ENTITY_SWITCH_KEY,\n withStrictError: 'Child of EntitySwitch is not an EntitySwitch.Case',\n })\n .getElements()\n .flatMap<SwitchCaseResult>((element: React.ReactElement) => {\n const { if: condition, children: elementsChildren } =\n element.props as SwitchCase;\n return [\n {\n if: condition?.(entity, { apis }) ?? true,\n children: elementsChildren,\n },\n ];\n }),\n [apis, entity],\n );\n const hasAsyncCases = results.some(\n r => typeof r.if === 'object' && 'then' in r.if,\n );\n\n if (hasAsyncCases) {\n return <AsyncEntitySwitch results={results} />;\n }\n\n return results.find(r => r.if)?.children ?? null;\n};\n\nfunction AsyncEntitySwitch({ results }: { results: SwitchCaseResult[] }) {\n const { loading, value } = useAsync(async () => {\n const promises = results.map(\n async ({ if: condition, children: output }) => {\n try {\n if (await condition) {\n return output;\n }\n } catch {\n /* ignored */\n }\n\n return null;\n },\n );\n return (await Promise.all(promises)).find(Boolean) ?? null;\n }, [results]);\n\n if (loading || !value) {\n return null;\n }\n\n return value;\n}\n\nEntitySwitch.Case = EntitySwitchCase;\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 { Entity, ComponentEntity } from '@backstage/catalog-model';\n\nfunction strCmp(a: string | undefined, b: string | undefined): boolean {\n return Boolean(\n a && a?.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US'),\n );\n}\n\nexport function isKind(kind: string) {\n return (entity: Entity) => strCmp(entity?.kind, kind);\n}\n\nexport function isComponentType(type: string) {\n return (entity: Entity) => {\n if (!strCmp(entity?.kind, 'component')) {\n return false;\n }\n const componentEntity = entity as ComponentEntity;\n return strCmp(componentEntity.spec.type, type);\n };\n}\n\nexport function isNamespace(namespace: string) {\n return (entity: Entity) => strCmp(entity?.metadata?.namespace, namespace);\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 { Grid } from '@material-ui/core';\nimport React, { PropsWithChildren } from 'react';\n\nexport const FilteredEntityLayout = ({ children }: PropsWithChildren<{}>) => (\n <Grid container style={{ position: 'relative' }}>\n {children}\n </Grid>\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 { BackstageTheme } from '@backstage/theme';\nimport {\n Box,\n Button,\n Drawer,\n Grid,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@material-ui/core';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport React, { useState, PropsWithChildren } from 'react';\n\nexport const FilterContainer = ({ children }: PropsWithChildren<{}>) => {\n const isMidSizeScreen = useMediaQuery<BackstageTheme>(theme =>\n theme.breakpoints.down('md'),\n );\n const theme = useTheme<BackstageTheme>();\n const [filterDrawerOpen, setFilterDrawerOpen] = useState<boolean>(false);\n\n return isMidSizeScreen ? (\n <>\n <Button\n style={{ marginTop: theme.spacing(1), marginLeft: theme.spacing(1) }}\n onClick={() => setFilterDrawerOpen(true)}\n startIcon={<FilterListIcon />}\n >\n Filters\n </Button>\n <Drawer\n open={filterDrawerOpen}\n onClose={() => setFilterDrawerOpen(false)}\n anchor=\"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 Filters\n </Typography>\n {children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {children}\n </Grid>\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 { Grid } from '@material-ui/core';\nimport React, { PropsWithChildren } from 'react';\n\nexport const EntityListContainer = ({ children }: PropsWithChildren<{}>) => (\n <Grid item xs={12} lg={10}>\n {children}\n </Grid>\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 Content,\n ContentHeader,\n CreateButton,\n PageWithHeader,\n SupportButton,\n TableColumn,\n TableProps,\n} from '@backstage/core-components';\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n EntityLifecyclePicker,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n EntityTypePicker,\n UserListFilterKind,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport React from 'react';\nimport { createComponentRouteRef } from '../../routes';\nimport { CatalogTable } from '../CatalogTable';\nimport { EntityRow } from '../CatalogTable/types';\nimport {\n FilteredEntityLayout,\n EntityListContainer,\n FilterContainer,\n} from '../FilteredEntityLayout';\nimport { CatalogKindHeader } from '../CatalogKindHeader';\n\n/**\n * DefaultCatalogPageProps\n * @public\n */\nexport type DefaultCatalogPageProps = {\n initiallySelectedFilter?: UserListFilterKind;\n columns?: TableColumn<EntityRow>[];\n actions?: TableProps<EntityRow>['actions'];\n};\n\nexport const DefaultCatalogPage = ({\n columns,\n actions,\n initiallySelectedFilter = 'owned',\n}: DefaultCatalogPageProps) => {\n const orgName =\n useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage';\n const createComponentLink = useRouteRef(createComponentRouteRef);\n\n return (\n <PageWithHeader title={`${orgName} Catalog`} themeId=\"home\">\n <EntityListProvider>\n <Content>\n <ContentHeader titleComponent={<CatalogKindHeader />}>\n <CreateButton\n title=\"Create Component\"\n to={createComponentLink && createComponentLink()}\n />\n <SupportButton>All your software catalog entities</SupportButton>\n </ContentHeader>\n <FilteredEntityLayout>\n <FilterContainer>\n <EntityTypePicker />\n <UserListPicker initialFilter={initiallySelectedFilter} />\n <EntityOwnerPicker />\n <EntityLifecyclePicker />\n <EntityTagPicker />\n </FilterContainer>\n <EntityListContainer>\n <CatalogTable columns={columns} actions={actions} />\n </EntityListContainer>\n </FilteredEntityLayout>\n </Content>\n </EntityListProvider>\n </PageWithHeader>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { useOutlet } from 'react-router';\nimport {\n DefaultCatalogPage,\n DefaultCatalogPageProps,\n} from './DefaultCatalogPage';\n\nexport const CatalogPage = (props: DefaultCatalogPageProps) => {\n const outlet = useOutlet();\n\n return outlet || <DefaultCatalogPage {...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 React from 'react';\nimport { makeStyles } from '@material-ui/core';\nimport IlloSvgUrl from './illo.svg';\n\nconst useStyles = makeStyles(theme => ({\n illo: {\n maxWidth: '60%',\n top: 100,\n right: 20,\n position: 'absolute',\n [theme.breakpoints.down('xs')]: {\n maxWidth: '96%',\n position: 'relative',\n top: 'unset',\n right: 'unset',\n margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`,\n },\n },\n}));\n\nexport const Illo = () => {\n const classes = useStyles();\n return (\n <img\n src={IlloSvgUrl}\n className={classes.illo}\n alt=\"Illustration on entity not found page\"\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 React from 'react';\nimport { Grid, Button, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { BackstageTheme } from '@backstage/theme';\n\nimport { Illo } from './Illo';\n\nconst useStyles = makeStyles<BackstageTheme>(theme => ({\n container: {\n paddingTop: theme.spacing(24),\n paddingLeft: theme.spacing(8),\n [theme.breakpoints.down('xs')]: {\n padding: theme.spacing(2),\n },\n },\n title: {\n paddingBottom: theme.spacing(2),\n [theme.breakpoints.down('xs')]: {\n fontSize: 32,\n },\n },\n body: {\n paddingBottom: theme.spacing(6),\n [theme.breakpoints.down('xs')]: {\n paddingBottom: theme.spacing(5),\n },\n },\n}));\n\nexport const EntityNotFound = () => {\n const classes = useStyles();\n\n return (\n <Grid container spacing={0} className={classes.container}>\n <Illo />\n <Grid item xs={12} sm={6}>\n <Typography variant=\"h2\" className={classes.title}>\n Entity was not found\n </Typography>\n <Typography variant=\"body1\" className={classes.body}>\n Want to help us build this? Check out our Getting Started\n documentation.\n </Typography>\n <Button\n variant=\"contained\"\n color=\"primary\"\n href=\"https://backstage.io/docs\"\n >\n DOCS\n </Button>\n </Grid>\n </Grid>\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 { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';\nimport {\n AsyncEntityProvider,\n useEntity,\n useEntityFromUrl,\n} from '@backstage/plugin-catalog-react';\nimport { Typography } from '@material-ui/core';\nimport React, { ComponentType, ReactNode } from 'react';\nimport { Navigate, Route, Routes, useParams } from 'react-router';\nimport { CatalogPage } from './CatalogPage';\nimport { EntityNotFound } from './EntityNotFound';\nimport { EntityPageLayout } from './EntityPageLayout';\nimport { Content, Link } from '@backstage/core-components';\n\nconst DefaultEntityPage = () => (\n <EntityPageLayout>\n <EntityPageLayout.Content\n path=\"/\"\n title=\"Overview\"\n element={\n <Content>\n <Typography variant=\"h2\">This is the default entity page.</Typography>\n <Typography variant=\"body1\">\n To override this component with your custom implementation, read\n docs on{' '}\n <Link to=\"https://backstage.io/docs\">backstage.io/docs</Link>\n </Typography>\n </Content>\n }\n />\n </EntityPageLayout>\n);\n\nconst EntityPageSwitch = ({ EntityPage }: { EntityPage: ComponentType }) => {\n const { entity, loading, error } = useEntity();\n // Loading and error states\n if (loading) return <EntityPageLayout />;\n if (error || !entity) return <EntityNotFound />;\n\n // Otherwise EntityPage provided from the App\n // Note that EntityPage will include EntityPageLayout already\n return <EntityPage />;\n};\n\nconst OldEntityRouteRedirect = () => {\n const { optionalNamespaceAndName, '*': rest } = useParams() as any;\n const [name, namespace] = optionalNamespaceAndName.split(':').reverse();\n const namespaceLower =\n namespace?.toLocaleLowerCase('en-US') ?? ENTITY_DEFAULT_NAMESPACE;\n const restWithSlash = rest ? `/${rest}` : '';\n return (\n <Navigate\n to={`../../${namespaceLower}/component/${name}${restWithSlash}`}\n />\n );\n};\n\nexport const EntityLoader = (props: { children: ReactNode }) => (\n <AsyncEntityProvider {...useEntityFromUrl()} {...props} />\n);\n\n/**\n * @deprecated Use plugin extensions instead\n * */\nexport const Router = ({\n EntityPage = DefaultEntityPage,\n}: {\n EntityPage?: ComponentType;\n}) => (\n <Routes>\n <Route path=\"/\" element={<CatalogPage />} />\n <Route\n path=\"/:namespace/:kind/:name\"\n element={\n <EntityLoader>\n <EntityPageSwitch EntityPage={EntityPage} />\n </EntityLoader>\n }\n />\n <Route\n path=\"Component/:optionalNamespaceAndName/*\"\n element={<OldEntityRouteRedirect />}\n />\n </Routes>\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 { CatalogClient } from '@backstage/catalog-client';\nimport {\n catalogApiRef,\n catalogRouteRef,\n DefaultStarredEntitiesApi,\n entityRouteRef,\n starredEntitiesApiRef,\n} from '@backstage/plugin-catalog-react';\nimport { createComponentRouteRef, viewTechDocRouteRef } from './routes';\nimport {\n createApiFactory,\n createComponentExtension,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\n\nexport const catalogPlugin = createPlugin({\n id: 'catalog',\n apis: [\n createApiFactory({\n api: catalogApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new CatalogClient({ discoveryApi, fetchApi }),\n }),\n createApiFactory({\n api: starredEntitiesApiRef,\n deps: { storageApi: storageApiRef },\n factory: ({ storageApi }) =>\n new DefaultStarredEntitiesApi({ storageApi }),\n }),\n ],\n routes: {\n catalogIndex: catalogRouteRef,\n catalogEntity: entityRouteRef,\n },\n externalRoutes: {\n createComponent: createComponentRouteRef,\n viewTechDoc: viewTechDocRouteRef,\n },\n});\n\nexport const CatalogIndexPage = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogIndexPage',\n component: () =>\n import('./components/CatalogPage').then(m => m.CatalogPage),\n mountPoint: catalogRouteRef,\n }),\n);\n\nexport const CatalogEntityPage = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogEntityPage',\n component: () =>\n import('./components/CatalogEntityPage').then(m => m.CatalogEntityPage),\n mountPoint: entityRouteRef,\n }),\n);\n\nexport const EntityAboutCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityAboutCard',\n component: {\n lazy: () => import('./components/AboutCard').then(m => m.AboutCard),\n },\n }),\n);\n\nexport const EntityLinksCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityLinksCard',\n component: {\n lazy: () =>\n import('./components/EntityLinksCard').then(m => m.EntityLinksCard),\n },\n }),\n);\n\nexport const EntityHasSystemsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSystemsCard',\n component: {\n lazy: () =>\n import('./components/HasSystemsCard').then(m => m.HasSystemsCard),\n },\n }),\n);\n\nexport const EntityHasComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasComponentsCard',\n component: {\n lazy: () =>\n import('./components/HasComponentsCard').then(m => m.HasComponentsCard),\n },\n }),\n);\n\nexport const EntityHasSubcomponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSubcomponentsCard',\n component: {\n lazy: () =>\n import('./components/HasSubcomponentsCard').then(\n m => m.HasSubcomponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityHasResourcesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasResourcesCard',\n component: {\n lazy: () =>\n import('./components/HasResourcesCard').then(m => m.HasResourcesCard),\n },\n }),\n);\n\nexport const EntityDependsOnComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependsOnComponentsCard').then(\n m => m.DependsOnComponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityDependencyOfComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependencyOfComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependencyOfComponentsCard').then(\n m => m.DependencyOfComponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityDependsOnResourcesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnResourcesCard',\n component: {\n lazy: () =>\n import('./components/DependsOnResourcesCard').then(\n m => m.DependsOnResourcesCard,\n ),\n },\n }),\n);\n\n/**\n * @deprecated This component is replaced by EntityCatalogGraphCard which is imported from `@backstage/plugin-catalog-graph`. This component will be removed in an\n * upcoming release\n */\nexport const EntitySystemDiagramCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntitySystemDiagramCard',\n component: {\n lazy: () =>\n import('./components/SystemDiagramCard').then(m => m.SystemDiagramCard),\n },\n }),\n);\n\nexport const RelatedEntitiesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'RelatedEntitiesCard',\n component: {\n lazy: () =>\n import('./components/RelatedEntitiesCard').then(\n m => m.RelatedEntitiesCard,\n ),\n },\n }),\n);\n"],"names":["useStyles","columnFactories.createNameColumn","columnFactories.createSystemColumn","columnFactories.createOwnerColumn","columnFactories.createSpecTypeColumn","columnFactories.createSpecLifecycleColumn","columnFactories.createMetadataDescriptionColumn","columnFactories.createTagsColumn","capitalize","Edit","makeStyles","headerProps","EntityLabels","Route"],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -188,6 +188,11 @@ declare type EntityPageLayoutProps = {
188
188
  UNSTABLE_contextMenuOptions?: contextMenuOptions;
189
189
  children?: React.ReactNode;
190
190
  };
191
+ /**
192
+ * Old entity page, only used by the old router based hierarchies.
193
+ *
194
+ * @deprecated Please use CatalogEntityPage instead
195
+ */
191
196
  declare const EntityPageLayout: {
192
197
  ({ children, UNSTABLE_extraContextMenuItems, UNSTABLE_contextMenuOptions, }: EntityPageLayoutProps): JSX.Element;
193
198
  Content: (_props: {
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- export { A as AboutCard, a as AboutContent, b as AboutField, c as CatalogClientWrapper, e as CatalogEntityPage, f as CatalogIndexPage, r as CatalogKindHeader, s as CatalogResultListItem, d as CatalogTable, E as EntityAboutCard, h as EntityDependencyOfComponentsCard, i as EntityDependsOnComponentsCard, j as EntityDependsOnResourcesCard, k as EntityHasComponentsCard, l as EntityHasResourcesCard, m as EntityHasSubcomponentsCard, n as EntityHasSystemsCard, B as EntityLayout, o as EntityLinksCard, Q as EntityListContainer, F as EntityOrphanWarning, J as EntityPageLayout, H as EntityProcessingErrorsPanel, K as EntitySwitch, p as EntitySystemDiagramCard, P as FilterContainer, O as FilteredEntityLayout, q as RelatedEntitiesCard, R as Router, g as catalogPlugin, y as createMetadataDescriptionColumn, t as createNameColumn, v as createOwnerColumn, x as createSpecLifecycleColumn, w as createSpecTypeColumn, u as createSystemColumn, z as createTagsColumn, I as hasCatalogProcessingErrors, N as isComponentType, L as isKind, M as isNamespace, G as isOrphan, g as plugin } from './esm/index-9e441058.esm.js';
1
+ export { A as AboutCard, a as AboutContent, b as AboutField, c as CatalogClientWrapper, e as CatalogEntityPage, f as CatalogIndexPage, r as CatalogKindHeader, s as CatalogResultListItem, d as CatalogTable, E as EntityAboutCard, h as EntityDependencyOfComponentsCard, i as EntityDependsOnComponentsCard, j as EntityDependsOnResourcesCard, k as EntityHasComponentsCard, l as EntityHasResourcesCard, m as EntityHasSubcomponentsCard, n as EntityHasSystemsCard, B as EntityLayout, o as EntityLinksCard, Q as EntityListContainer, F as EntityOrphanWarning, J as EntityPageLayout, H as EntityProcessingErrorsPanel, K as EntitySwitch, p as EntitySystemDiagramCard, P as FilterContainer, O as FilteredEntityLayout, q as RelatedEntitiesCard, R as Router, g as catalogPlugin, y as createMetadataDescriptionColumn, t as createNameColumn, v as createOwnerColumn, x as createSpecLifecycleColumn, w as createSpecTypeColumn, u as createSystemColumn, z as createTagsColumn, I as hasCatalogProcessingErrors, N as isComponentType, L as isKind, M as isNamespace, G as isOrphan, g as plugin } from './esm/index-da7631a3.esm.js';
2
2
  import '@backstage/catalog-model';
3
3
  import '@backstage/core-components';
4
4
  import '@backstage/core-plugin-api';
@@ -15,6 +15,7 @@ import '@material-ui/lab';
15
15
  import 'react-router';
16
16
  import '@material-ui/core/styles';
17
17
  import '@material-ui/icons/Cancel';
18
+ import '@material-ui/icons/BugReport';
18
19
  import '@material-ui/icons/MoreVert';
19
20
  import '@backstage/plugin-catalog-common';
20
21
  import '@backstage/errors';
@@ -1 +1 @@
1
- {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog",
3
3
  "description": "The Backstage plugin for browsing the Backstage catalog",
4
- "version": "0.7.12-next.0",
4
+ "version": "0.7.12",
5
5
  "main": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -31,14 +31,14 @@
31
31
  "clean": "backstage-cli clean"
32
32
  },
33
33
  "dependencies": {
34
- "@backstage/catalog-client": "^0.5.5",
34
+ "@backstage/catalog-client": "^0.6.0",
35
35
  "@backstage/catalog-model": "^0.9.10",
36
- "@backstage/core-components": "^0.8.8-next.0",
36
+ "@backstage/core-components": "^0.8.8",
37
37
  "@backstage/core-plugin-api": "^0.6.0",
38
38
  "@backstage/errors": "^0.2.0",
39
- "@backstage/integration-react": "^0.1.21-next.0",
39
+ "@backstage/integration-react": "^0.1.21",
40
40
  "@backstage/plugin-catalog-common": "^0.1.2",
41
- "@backstage/plugin-catalog-react": "^0.6.14-next.0",
41
+ "@backstage/plugin-catalog-react": "^0.6.14",
42
42
  "@backstage/theme": "^0.2.14",
43
43
  "@material-ui/core": "^4.12.2",
44
44
  "@material-ui/icons": "^4.9.1",
@@ -54,9 +54,9 @@
54
54
  "react": "^16.13.1 || ^17.0.0"
55
55
  },
56
56
  "devDependencies": {
57
- "@backstage/cli": "^0.13.2-next.0",
57
+ "@backstage/cli": "^0.13.2",
58
58
  "@backstage/core-app-api": "^0.5.2",
59
- "@backstage/dev-utils": "^0.2.21-next.0",
59
+ "@backstage/dev-utils": "^0.2.21",
60
60
  "@backstage/plugin-permission-react": "^0.3.0",
61
61
  "@backstage/test-utils": "^0.2.4",
62
62
  "@testing-library/jest-dom": "^5.10.1",
@@ -68,5 +68,5 @@
68
68
  "files": [
69
69
  "dist"
70
70
  ],
71
- "gitHead": "e6f167225d843beeb974c287c3364d951b587626"
71
+ "gitHead": "4f4bc77a4152d372b10a4e8d97d92f00e23f3b56"
72
72
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-57f985a3.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-9e441058.esm.js","sources":["../../src/CatalogClientWrapper.ts","../../src/routes.ts","../../src/components/AboutCard/AboutField.tsx","../../src/components/AboutCard/AboutContent.tsx","../../src/components/AboutCard/AboutCard.tsx","../../src/components/CatalogKindHeader/CatalogKindHeader.tsx","../../src/components/CatalogResultListItem/CatalogResultListItem.tsx","../../src/components/CatalogTable/columns.tsx","../../src/components/CatalogTable/CatalogTable.tsx","../../src/components/EntityContextMenu/EntityContextMenu.tsx","../../src/components/EntityLayout/EntityLayout.tsx","../../src/components/EntityOrphanWarning/DeleteEntityDialog.tsx","../../src/components/EntityOrphanWarning/EntityOrphanWarning.tsx","../../src/components/EntityProcessingErrorsPanel/EntityProcessingErrorsPanel.tsx","../../src/components/EntityPageLayout/Tabbed/Tabbed.tsx","../../src/components/EntityPageLayout/EntityPageLayout.tsx","../../src/components/EntitySwitch/EntitySwitch.tsx","../../src/components/EntitySwitch/conditions.ts","../../src/components/FilteredEntityLayout/FilteredEntityLayout.tsx","../../src/components/FilteredEntityLayout/FilterContainer.tsx","../../src/components/FilteredEntityLayout/EntityListContainer.tsx","../../src/components/CatalogPage/DefaultCatalogPage.tsx","../../src/components/CatalogPage/CatalogPage.tsx","../../src/components/EntityNotFound/Illo/Illo.tsx","../../src/components/EntityNotFound/EntityNotFound.tsx","../../src/components/Router.tsx","../../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { Entity, EntityName, Location } from '@backstage/catalog-model';\nimport {\n AddLocationRequest,\n AddLocationResponse,\n CatalogApi,\n CatalogClient,\n CatalogEntitiesRequest,\n CatalogListResponse,\n CatalogRequestOptions,\n CatalogEntityAncestorsRequest,\n CatalogEntityAncestorsResponse,\n} from '@backstage/catalog-client';\nimport { IdentityApi } from '@backstage/core-plugin-api';\n\n/**\n * CatalogClient wrapper that injects identity token for all requests\n *\n * @deprecated The default catalog client now uses the `fetchApiRef`\n * implementation, which in turn by default issues tokens just the same as this\n * class used to assist in doing. If you use a custom `fetchApiRef`\n * implementation that does NOT issue tokens, or use a custom `catalogApiRef`\n * implementation which does not use the default `fetchApiRef`, you can wrap\n * your catalog API in this class to get back the old behavior.\n */\nexport class CatalogClientWrapper implements CatalogApi {\n private readonly identityApi: IdentityApi;\n private readonly client: CatalogClient;\n\n constructor(options: { client: CatalogClient; identityApi: IdentityApi }) {\n this.client = options.client;\n this.identityApi = options.identityApi;\n }\n\n async getLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getLocationById(\n id,\n await this.getCredentials(options),\n );\n }\n\n async getEntities(\n request?: CatalogEntitiesRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogListResponse<Entity>> {\n return await this.client.getEntities(\n request,\n await this.getCredentials(options),\n );\n }\n\n async getEntityByName(\n compoundName: EntityName,\n options?: CatalogRequestOptions,\n ): Promise<Entity | undefined> {\n return await this.client.getEntityByName(\n compoundName,\n await this.getCredentials(options),\n );\n }\n\n async addLocation(\n request: AddLocationRequest,\n options?: CatalogRequestOptions,\n ): Promise<AddLocationResponse> {\n return await this.client.addLocation(\n request,\n await this.getCredentials(options),\n );\n }\n\n async getOriginLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getOriginLocationByEntity(\n entity,\n await this.getCredentials(options),\n );\n }\n\n async getLocationByEntity(\n entity: Entity,\n options?: CatalogRequestOptions,\n ): Promise<Location | undefined> {\n return await this.client.getLocationByEntity(\n entity,\n await this.getCredentials(options),\n );\n }\n\n async removeLocationById(\n id: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.removeLocationById(\n id,\n await this.getCredentials(options),\n );\n }\n\n async removeEntityByUid(\n uid: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.removeEntityByUid(\n uid,\n await this.getCredentials(options),\n );\n }\n\n async refreshEntity(\n entityRef: string,\n options?: CatalogRequestOptions,\n ): Promise<void> {\n return await this.client.refreshEntity(\n entityRef,\n await this.getCredentials(options),\n );\n }\n\n async getEntityAncestors(\n request: CatalogEntityAncestorsRequest,\n options?: CatalogRequestOptions,\n ): Promise<CatalogEntityAncestorsResponse> {\n return await this.client.getEntityAncestors(\n request,\n await this.getCredentials(options),\n );\n }\n\n private async getCredentials(\n options?: CatalogRequestOptions,\n ): Promise<{ token?: string }> {\n if (options?.token) {\n return { token: options?.token };\n }\n return this.identityApi.getCredentials();\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 { createExternalRouteRef } from '@backstage/core-plugin-api';\n\nexport const createComponentRouteRef = createExternalRouteRef({\n id: 'create-component',\n optional: true,\n});\n\nexport const viewTechDocRouteRef = createExternalRouteRef({\n id: 'view-techdoc',\n optional: true,\n params: ['namespace', 'kind', 'name'],\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 { useElementFilter } from '@backstage/core-plugin-api';\nimport { Grid, makeStyles, Typography } from '@material-ui/core';\nimport React from 'react';\n\nconst useStyles = makeStyles(theme => ({\n value: {\n fontWeight: 'bold',\n overflow: 'hidden',\n lineHeight: '24px',\n wordBreak: 'break-word',\n },\n label: {\n color: theme.palette.text.secondary,\n textTransform: 'uppercase',\n fontSize: '10px',\n fontWeight: 'bold',\n letterSpacing: 0.5,\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n },\n}));\n\ntype Props = {\n label: string;\n value?: string;\n gridSizes?: Record<string, number>;\n children?: React.ReactNode;\n};\n\nexport const AboutField = ({ label, value, gridSizes, children }: Props) => {\n const classes = useStyles();\n\n const childElements = useElementFilter(children, c => c.getElements());\n\n // Content is either children or a string prop `value`\n const content =\n childElements.length > 0 ? (\n childElements\n ) : (\n <Typography variant=\"body2\" className={classes.value}>\n {value || `unknown`}\n </Typography>\n );\n return (\n <Grid item {...gridSizes}>\n <Typography variant=\"subtitle2\" className={classes.label}>\n {label}\n </Typography>\n {content}\n </Grid>\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 Entity,\n RELATION_OWNED_BY,\n RELATION_PART_OF,\n} from '@backstage/catalog-model';\nimport {\n EntityRefLinks,\n getEntityRelations,\n} from '@backstage/plugin-catalog-react';\nimport { Chip, Grid, makeStyles, Typography } from '@material-ui/core';\nimport React from 'react';\nimport { AboutField } from './AboutField';\n\nconst useStyles = makeStyles({\n description: {\n wordBreak: 'break-word',\n },\n});\n\ntype Props = {\n entity: Entity;\n};\n\nexport const AboutContent = ({ entity }: Props) => {\n const classes = useStyles();\n const isSystem = entity.kind.toLocaleLowerCase('en-US') === 'system';\n const isResource = entity.kind.toLocaleLowerCase('en-US') === 'resource';\n const isComponent = entity.kind.toLocaleLowerCase('en-US') === 'component';\n const isAPI = entity.kind.toLocaleLowerCase('en-US') === 'api';\n const isTemplate = entity.kind.toLocaleLowerCase('en-US') === 'template';\n const isLocation = entity.kind.toLocaleLowerCase('en-US') === 'location';\n const isGroup = entity.kind.toLocaleLowerCase('en-US') === 'group';\n\n const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'system',\n });\n const partOfComponentRelations = getEntityRelations(\n entity,\n RELATION_PART_OF,\n {\n kind: 'component',\n },\n );\n const partOfDomainRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'domain',\n });\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return (\n <Grid container>\n <AboutField label=\"Description\" gridSizes={{ xs: 12 }}>\n <Typography variant=\"body2\" paragraph className={classes.description}>\n {entity?.metadata?.description || 'No description'}\n </Typography>\n </AboutField>\n <AboutField\n label=\"Owner\"\n value=\"No Owner\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {ownedByRelations.length > 0 && (\n <EntityRefLinks entityRefs={ownedByRelations} defaultKind=\"group\" />\n )}\n </AboutField>\n {(isSystem || partOfDomainRelations.length > 0) && (\n <AboutField\n label=\"Domain\"\n value=\"No Domain\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {partOfDomainRelations.length > 0 && (\n <EntityRefLinks\n entityRefs={partOfDomainRelations}\n defaultKind=\"domain\"\n />\n )}\n </AboutField>\n )}\n {(isAPI ||\n isComponent ||\n isResource ||\n partOfSystemRelations.length > 0) && (\n <AboutField\n label=\"System\"\n value=\"No System\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {partOfSystemRelations.length > 0 && (\n <EntityRefLinks\n entityRefs={partOfSystemRelations}\n defaultKind=\"system\"\n />\n )}\n </AboutField>\n )}\n {isComponent && partOfComponentRelations.length > 0 && (\n <AboutField\n label=\"Parent Component\"\n value=\"No Parent Component\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n <EntityRefLinks\n entityRefs={partOfComponentRelations}\n defaultKind=\"component\"\n />\n </AboutField>\n )}\n {(isAPI ||\n isComponent ||\n isResource ||\n isTemplate ||\n isGroup ||\n isLocation ||\n typeof entity?.spec?.type === 'string') && (\n <AboutField\n label=\"Type\"\n value={entity?.spec?.type as string}\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n />\n )}\n {(isAPI ||\n isComponent ||\n typeof entity?.spec?.lifecycle === 'string') && (\n <AboutField\n label=\"Lifecycle\"\n value={entity?.spec?.lifecycle as string}\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n />\n )}\n <AboutField\n label=\"Tags\"\n value=\"No Tags\"\n gridSizes={{ xs: 12, sm: 6, lg: 4 }}\n >\n {(entity?.metadata?.tags || []).map(t => (\n <Chip key={t} size=\"small\" label={t} />\n ))}\n </AboutField>\n </Grid>\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 Entity,\n ENTITY_DEFAULT_NAMESPACE,\n LOCATION_ANNOTATION,\n stringifyEntityRef,\n} from '@backstage/catalog-model';\nimport {\n HeaderIconLinkRow,\n IconLinkVerticalProps,\n InfoCardVariants,\n Link,\n} from '@backstage/core-components';\nimport { alertApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n ScmIntegrationIcon,\n scmIntegrationsApiRef,\n} from '@backstage/integration-react';\nimport {\n catalogApiRef,\n getEntityMetadataEditUrl,\n getEntitySourceLocation,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport {\n Card,\n CardContent,\n CardHeader,\n Divider,\n IconButton,\n makeStyles,\n} from '@material-ui/core';\nimport CachedIcon from '@material-ui/icons/Cached';\nimport DocsIcon from '@material-ui/icons/Description';\nimport EditIcon from '@material-ui/icons/Edit';\nimport React, { useCallback } from 'react';\nimport { viewTechDocRouteRef } from '../../routes';\nimport { AboutContent } from './AboutContent';\n\nconst useStyles = makeStyles({\n gridItemCard: {\n display: 'flex',\n flexDirection: 'column',\n height: 'calc(100% - 10px)', // for pages without content header\n marginBottom: '10px',\n },\n fullHeightCard: {\n display: 'flex',\n flexDirection: 'column',\n height: '100%',\n },\n gridItemCardContent: {\n flex: 1,\n },\n fullHeightCardContent: {\n flex: 1,\n },\n});\n\ntype AboutCardProps = {\n /** @deprecated The entity is now grabbed from context instead */\n entity?: Entity;\n variant?: InfoCardVariants;\n};\n\nexport function AboutCard({ variant }: AboutCardProps) {\n const classes = useStyles();\n const { entity } = useEntity();\n const scmIntegrationsApi = useApi(scmIntegrationsApiRef);\n const catalogApi = useApi(catalogApiRef);\n const alertApi = useApi(alertApiRef);\n const viewTechdocLink = useRouteRef(viewTechDocRouteRef);\n\n const entitySourceLocation = getEntitySourceLocation(\n entity,\n scmIntegrationsApi,\n );\n const entityMetadataEditUrl = getEntityMetadataEditUrl(entity);\n\n const viewInSource: IconLinkVerticalProps = {\n label: 'View Source',\n disabled: !entitySourceLocation,\n icon: <ScmIntegrationIcon type={entitySourceLocation?.integrationType} />,\n href: entitySourceLocation?.locationTargetUrl,\n };\n const viewInTechDocs: IconLinkVerticalProps = {\n label: 'View TechDocs',\n disabled:\n !entity.metadata.annotations?.['backstage.io/techdocs-ref'] ||\n !viewTechdocLink,\n icon: <DocsIcon />,\n href:\n viewTechdocLink &&\n viewTechdocLink({\n namespace: entity.metadata.namespace || ENTITY_DEFAULT_NAMESPACE,\n kind: entity.kind,\n name: entity.metadata.name,\n }),\n };\n\n let cardClass = '';\n if (variant === 'gridItem') {\n cardClass = classes.gridItemCard;\n } else if (variant === 'fullHeight') {\n cardClass = classes.fullHeightCard;\n }\n\n let cardContentClass = '';\n if (variant === 'gridItem') {\n cardContentClass = classes.gridItemCardContent;\n } else if (variant === 'fullHeight') {\n cardContentClass = classes.fullHeightCardContent;\n }\n\n const entityLocation = entity.metadata.annotations?.[LOCATION_ANNOTATION];\n // Limiting the ability to manually refresh to the less expensive locations\n const allowRefresh =\n entityLocation?.startsWith('url:') || entityLocation?.startsWith('file:');\n const refreshEntity = useCallback(async () => {\n await catalogApi.refreshEntity(stringifyEntityRef(entity));\n alertApi.post({ message: 'Refresh scheduled', severity: 'info' });\n }, [catalogApi, alertApi, entity]);\n\n return (\n <Card className={cardClass}>\n <CardHeader\n title=\"About\"\n action={\n <>\n {allowRefresh && (\n <IconButton\n aria-label=\"Refresh\"\n title=\"Schedule entity refresh\"\n onClick={refreshEntity}\n >\n <CachedIcon />\n </IconButton>\n )}\n <IconButton\n component={Link}\n aria-label=\"Edit\"\n disabled={!entityMetadataEditUrl}\n title=\"Edit Metadata\"\n to={entityMetadataEditUrl ?? '#'}\n >\n <EditIcon />\n </IconButton>\n </>\n }\n subheader={<HeaderIconLinkRow links={[viewInSource, viewInTechDocs]} />}\n />\n <Divider />\n <CardContent className={cardContentClass}>\n <AboutContent entity={entity} />\n </CardContent>\n </Card>\n );\n}\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React, { useEffect, useState } from 'react';\nimport {\n capitalize,\n createStyles,\n InputBase,\n makeStyles,\n MenuItem,\n Select,\n Theme,\n} from '@material-ui/core';\nimport {\n EntityKindFilter,\n useEntityKinds,\n useEntityListProvider,\n} from '@backstage/plugin-catalog-react';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n root: {\n ...theme.typography.h4,\n },\n }),\n);\n\ntype CatalogKindHeaderProps = {\n initialFilter?: string;\n};\n\nexport const CatalogKindHeader = ({\n initialFilter = 'component',\n}: CatalogKindHeaderProps) => {\n const classes = useStyles();\n const { kinds: allKinds = [] } = useEntityKinds();\n const { updateFilters, queryParameters } = useEntityListProvider();\n\n const [selectedKind, setSelectedKind] = useState(\n ([queryParameters.kind].flat()[0] ?? initialFilter).toLocaleLowerCase(\n 'en-US',\n ),\n );\n\n useEffect(() => {\n updateFilters({\n kind: selectedKind ? new EntityKindFilter(selectedKind) : undefined,\n });\n }, [selectedKind, updateFilters]);\n\n // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not\n // be present in allKinds. It should still be shown in the dropdown, but may not have the nice\n // enforced casing from the catalog-backend. This makes a key/value record for the Select options,\n // including selectedKind if it's unknown - but allows the selectedKind to get clobbered by the\n // more proper catalog kind if it exists.\n const options = [capitalize(selectedKind)]\n .concat(allKinds)\n .sort()\n .reduce((acc, kind) => {\n acc[kind.toLocaleLowerCase('en-US')] = kind;\n return acc;\n }, {} as Record<string, string>);\n\n return (\n <Select\n input={<InputBase value={selectedKind} />}\n value={selectedKind}\n onChange={e => setSelectedKind(e.target.value as string)}\n classes={classes}\n >\n {Object.keys(options).map(kind => (\n <MenuItem value={kind} key={kind}>\n {`${options[kind]}s`}\n </MenuItem>\n ))}\n </Select>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport {\n Box,\n Chip,\n Divider,\n ListItem,\n ListItemText,\n makeStyles,\n} from '@material-ui/core';\nimport { Link } from '@backstage/core-components';\n\nconst useStyles = makeStyles({\n flexContainer: {\n flexWrap: 'wrap',\n },\n itemText: {\n width: '100%',\n wordBreak: 'break-all',\n marginBottom: '1rem',\n },\n});\n\nexport const CatalogResultListItem = ({ result }: any) => {\n const classes = useStyles();\n return (\n <Link to={result.location}>\n <ListItem alignItems=\"flex-start\" className={classes.flexContainer}>\n <ListItemText\n className={classes.itemText}\n primaryTypographyProps={{ variant: 'h6' }}\n primary={result.title}\n secondary={result.text}\n />\n <Box>\n {result.kind && <Chip label={`Kind: ${result.kind}`} size=\"small\" />}\n {result.lifecycle && (\n <Chip label={`Lifecycle: ${result.lifecycle}`} size=\"small\" />\n )}\n </Box>\n </ListItem>\n <Divider component=\"li\" />\n </Link>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport {\n formatEntityRefTitle,\n EntityRefLink,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Chip } from '@material-ui/core';\nimport { EntityRow } from './types';\nimport { OverflowTooltip, TableColumn } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\n\ntype NameColumnProps = {\n defaultKind?: string;\n};\n\nexport function createNameColumn(\n props?: NameColumnProps,\n): TableColumn<EntityRow> {\n function formatContent(entity: Entity): string {\n return (\n entity.metadata?.title ||\n formatEntityRefTitle(entity, {\n defaultKind: props?.defaultKind,\n })\n );\n }\n\n return {\n title: 'Name',\n field: 'resolved.name',\n highlight: true,\n customSort({ entity: entity1 }, { entity: entity2 }) {\n // TODO: We could implement this more efficiently by comparing field by field.\n // This has similar issues as above.\n return formatContent(entity1).localeCompare(formatContent(entity2));\n },\n render: ({ entity }) => (\n <EntityRefLink\n entityRef={entity}\n defaultKind={props?.defaultKind || 'Component'}\n title={entity.metadata?.title}\n />\n ),\n };\n}\n\nexport function createSystemColumn(): TableColumn<EntityRow> {\n return {\n title: 'System',\n field: 'resolved.partOfSystemRelationTitle',\n render: ({ resolved }) => (\n <EntityRefLinks\n entityRefs={resolved.partOfSystemRelations}\n defaultKind=\"system\"\n />\n ),\n };\n}\n\nexport function createOwnerColumn(): TableColumn<EntityRow> {\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\nexport function createSpecTypeColumn(): TableColumn<EntityRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n hidden: true,\n };\n}\n\nexport function createSpecLifecycleColumn(): TableColumn<EntityRow> {\n return {\n title: 'Lifecycle',\n field: 'entity.spec.lifecycle',\n };\n}\n\nexport function createMetadataDescriptionColumn(): TableColumn<EntityRow> {\n return {\n title: 'Description',\n field: 'entity.metadata.description',\n render: ({ entity }) => (\n <OverflowTooltip\n text={entity.metadata.description}\n placement=\"bottom-start\"\n />\n ),\n width: 'auto',\n };\n}\n\nexport function createTagsColumn(): TableColumn<EntityRow> {\n return {\n title: 'Tags',\n field: 'entity.metadata.tags',\n cellStyle: {\n padding: '0px 16px 0px 20px',\n },\n render: ({ entity }) => (\n <>\n {entity.metadata.tags &&\n entity.metadata.tags.map(t => (\n <Chip\n key={t}\n label={t}\n size=\"small\"\n variant=\"outlined\"\n style={{ marginBottom: '0px' }}\n />\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 */\nimport { RELATION_OWNED_BY, RELATION_PART_OF } from '@backstage/catalog-model';\nimport {\n favoriteEntityIcon,\n favoriteEntityTooltip,\n formatEntityRefTitle,\n getEntityMetadataEditUrl,\n getEntityMetadataViewUrl,\n getEntityRelations,\n useEntityListProvider,\n useStarredEntities,\n} from '@backstage/plugin-catalog-react';\nimport Edit from '@material-ui/icons/Edit';\nimport OpenInNew from '@material-ui/icons/OpenInNew';\nimport { capitalize } from 'lodash';\nimport React, { useMemo } from 'react';\nimport * as columnFactories from './columns';\nimport { EntityRow } from './types';\nimport {\n CodeSnippet,\n Table,\n TableColumn,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\n\ntype CatalogTableProps = {\n columns?: TableColumn<EntityRow>[];\n actions?: TableProps<EntityRow>['actions'];\n};\n\nexport const CatalogTable = ({ columns, actions }: CatalogTableProps) => {\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const { loading, error, entities, filters } = useEntityListProvider();\n\n const defaultColumns: TableColumn<EntityRow>[] = useMemo(\n () => [\n columnFactories.createNameColumn({ defaultKind: filters.kind?.value }),\n columnFactories.createSystemColumn(),\n columnFactories.createOwnerColumn(),\n columnFactories.createSpecTypeColumn(),\n columnFactories.createSpecLifecycleColumn(),\n columnFactories.createMetadataDescriptionColumn(),\n columnFactories.createTagsColumn(),\n ],\n [filters.kind?.value],\n );\n\n const showTypeColumn = filters.type === undefined;\n // TODO(timbonicus): remove the title from the CatalogTable once using EntitySearchBar\n const titlePreamble = capitalize(filters.user?.value ?? 'all');\n\n if (error) {\n return (\n <div>\n <WarningPanel\n severity=\"error\"\n title=\"Could not fetch catalog entities.\"\n >\n <CodeSnippet language=\"text\" text={error.toString()} />\n </WarningPanel>\n </div>\n );\n }\n\n const defaultActions: TableProps<EntityRow>['actions'] = [\n ({ entity }) => {\n const url = getEntityMetadataViewUrl(entity);\n return {\n icon: () => <OpenInNew aria-label=\"View\" fontSize=\"small\" />,\n tooltip: 'View',\n disabled: !url,\n onClick: () => {\n if (!url) return;\n window.open(url, '_blank');\n },\n };\n },\n ({ entity }) => {\n const url = getEntityMetadataEditUrl(entity);\n return {\n icon: () => <Edit aria-label=\"Edit\" fontSize=\"small\" />,\n tooltip: 'Edit',\n disabled: !url,\n onClick: () => {\n if (!url) return;\n window.open(url, '_blank');\n },\n };\n },\n ({ entity }) => {\n const isStarred = isStarredEntity(entity);\n return {\n cellStyle: { paddingLeft: '1em' },\n icon: () => favoriteEntityIcon(isStarred),\n tooltip: favoriteEntityTooltip(isStarred),\n onClick: () => toggleStarredEntity(entity),\n };\n },\n ];\n\n const rows = entities.map(entity => {\n const partOfSystemRelations = getEntityRelations(entity, RELATION_PART_OF, {\n kind: 'system',\n });\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n\n return {\n entity,\n resolved: {\n name: formatEntityRefTitle(entity, {\n defaultKind: 'Component',\n }),\n ownedByRelationsTitle: ownedByRelations\n .map(r => formatEntityRefTitle(r, { defaultKind: 'group' }))\n .join(', '),\n ownedByRelations,\n partOfSystemRelationTitle: partOfSystemRelations\n .map(r =>\n formatEntityRefTitle(r, {\n defaultKind: 'system',\n }),\n )\n .join(', '),\n partOfSystemRelations,\n },\n };\n });\n\n const typeColumn = (columns || defaultColumns).find(c => c.title === 'Type');\n if (typeColumn) {\n typeColumn.hidden = !showTypeColumn;\n }\n const showPagination = rows.length > 20;\n\n return (\n <Table<EntityRow>\n isLoading={loading}\n columns={columns || defaultColumns}\n options={{\n paging: showPagination,\n pageSize: 20,\n actionsColumnIndex: -1,\n loadingType: 'linear',\n showEmptyDataSourceMessage: !loading,\n padding: 'dense',\n pageSizeOptions: [20, 50, 100],\n }}\n title={`${titlePreamble} (${entities.length})`}\n data={rows}\n actions={actions || defaultActions}\n />\n );\n};\n\nCatalogTable.columns = columnFactories;\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 Divider,\n IconButton,\n ListItemIcon,\n ListItemText,\n MenuItem,\n MenuList,\n Popover,\n} from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Cancel from '@material-ui/icons/Cancel';\nimport MoreVert from '@material-ui/icons/MoreVert';\nimport React, { useState } from 'react';\nimport { IconComponent } from '@backstage/core-plugin-api';\nimport { useEntityPermission } from '@backstage/plugin-catalog-react';\nimport { catalogEntityDeletePermission } from '@backstage/plugin-catalog-common';\n\n// TODO(freben): It should probably instead be the case that Header sets the theme text color to white inside itself unconditionally instead\nconst useStyles = makeStyles({\n button: {\n color: 'white',\n },\n});\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype Props = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n onUnregisterEntity: () => void;\n};\n\nexport const EntityContextMenu = ({\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n onUnregisterEntity,\n}: Props) => {\n const [anchorEl, setAnchorEl] = useState<HTMLButtonElement>();\n const classes = useStyles();\n const unregisterPermission = useEntityPermission(\n catalogEntityDeletePermission,\n );\n\n const onOpen = (event: React.SyntheticEvent<HTMLButtonElement>) => {\n setAnchorEl(event.currentTarget);\n };\n\n const onClose = () => {\n setAnchorEl(undefined);\n };\n\n const extraItems = UNSTABLE_extraContextMenuItems && [\n ...UNSTABLE_extraContextMenuItems.map(item => (\n <MenuItem\n key={item.title}\n onClick={() => {\n onClose();\n item.onClick();\n }}\n >\n <ListItemIcon>\n <item.Icon fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary={item.title} />\n </MenuItem>\n )),\n <Divider key=\"the divider is here!\" />,\n ];\n\n const disableUnregister =\n (!unregisterPermission.allowed ||\n UNSTABLE_contextMenuOptions?.disableUnregister) ??\n false;\n\n return (\n <>\n <IconButton\n aria-label=\"more\"\n aria-controls=\"long-menu\"\n aria-haspopup=\"true\"\n onClick={onOpen}\n data-testid=\"menu-button\"\n className={classes.button}\n >\n <MoreVert />\n </IconButton>\n <Popover\n open={Boolean(anchorEl)}\n onClose={onClose}\n anchorEl={anchorEl}\n anchorOrigin={{ vertical: 'bottom', horizontal: 'right' }}\n transformOrigin={{ vertical: 'top', horizontal: 'right' }}\n >\n <MenuList>\n {extraItems}\n <MenuItem\n onClick={() => {\n onClose();\n onUnregisterEntity();\n }}\n disabled={disableUnregister}\n >\n <ListItemIcon>\n <Cancel fontSize=\"small\" />\n </ListItemIcon>\n <ListItemText primary=\"Unregister entity\" />\n </MenuItem>\n </MenuList>\n </Popover>\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 {\n Entity,\n ENTITY_DEFAULT_NAMESPACE,\n RELATION_OWNED_BY,\n} from '@backstage/catalog-model';\nimport {\n Content,\n Header,\n HeaderLabel,\n Link,\n Page,\n Progress,\n RoutedTabs,\n WarningPanel,\n} from '@backstage/core-components';\nimport {\n attachComponentData,\n IconComponent,\n useElementFilter,\n} from '@backstage/core-plugin-api';\nimport {\n EntityContext,\n EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n UnregisterEntityDialog,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box, TabProps } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useContext, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\n\ntype SubRoute = {\n path: string;\n title: string;\n children: JSX.Element;\n if?: (entity: Entity) => boolean;\n tabProps?: TabProps<React.ElementType, { component?: React.ElementType }>;\n};\n\nconst dataKey = 'plugin.catalog.entityLayoutRoute';\n\nconst Route: (props: SubRoute) => null = () => null;\nattachComponentData(Route, dataKey, true);\n\n// This causes all mount points that are discovered within this route to use the path of the route itself\nattachComponentData(Route, 'core.gatherMountPoints', true);\n\nconst EntityLayoutTitle = ({\n entity,\n title,\n}: {\n title: string;\n entity: Entity | undefined;\n}) => {\n return (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\" maxWidth=\"100%\">\n <Box\n component=\"span\"\n textOverflow=\"ellipsis\"\n whiteSpace=\"nowrap\"\n overflow=\"hidden\"\n >\n {title}\n </Box>\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n );\n};\n\nconst headerProps = (\n paramKind: string | undefined,\n paramNamespace: string | undefined,\n paramName: string | undefined,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } => {\n const kind = paramKind ?? entity?.kind ?? '';\n const namespace = paramNamespace ?? entity?.metadata.namespace ?? '';\n const name =\n entity?.metadata.title ?? paramName ?? entity?.metadata.name ?? '';\n return {\n headerTitle: `${name}${\n namespace && namespace !== ENTITY_DEFAULT_NAMESPACE\n ? ` in ${namespace}`\n : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n};\n\nconst EntityLabels = ({ entity }: { entity: Entity }) => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel label=\"Lifecycle\" value={entity.spec.lifecycle} />\n )}\n </>\n );\n};\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype EntityLayoutProps = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n children?: React.ReactNode;\n};\n\n/**\n * EntityLayout is a compound component, which allows you to define a layout for\n * entities using a sub-navigation mechanism.\n *\n * Consists of two parts: EntityLayout and EntityLayout.Route\n *\n * @example\n * ```jsx\n * <EntityLayout>\n * <EntityLayout.Route path=\"/example\" title=\"Example tab\">\n * <div>This is rendered under /example/anything-here route</div>\n * </EntityLayout.Route>\n * </EntityLayout>\n * ```\n */\nexport const EntityLayout = ({\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n children,\n}: EntityLayoutProps) => {\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useContext(EntityContext);\n const routes = useElementFilter(\n children,\n elements =>\n elements\n .selectByComponentData({\n key: dataKey,\n withStrictError:\n 'Child of EntityLayout must be an EntityLayout.Route',\n })\n .getElements<SubRoute>() // all nodes, element data, maintain structure or not?\n .flatMap(({ props }) => {\n if (props.if && entity && !props.if(entity)) {\n return [];\n }\n\n return [\n {\n path: props.path,\n title: props.title,\n children: props.children,\n tabProps: props.tabProps,\n },\n ];\n }),\n [entity],\n );\n\n const { headerTitle, headerType } = headerProps(\n kind,\n namespace,\n name,\n entity,\n );\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const navigate = useNavigate();\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n navigate('/');\n };\n\n const showRemovalDialog = () => setConfirmationDialogOpen(true);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n <Header\n title={<EntityLayoutTitle title={headerTitle} entity={entity!} />}\n pageTitleOverride={headerTitle}\n type={headerType}\n >\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n onUnregisterEntity={showRemovalDialog}\n />\n </>\n )}\n </Header>\n\n {loading && <Progress />}\n\n {entity && <RoutedTabs routes={routes} />}\n\n {error && (\n <Content>\n <Alert severity=\"error\">{error.toString()}</Alert>\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n <WarningPanel title=\"Entity not found\">\n There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n </Content>\n )}\n\n <UnregisterEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\n />\n </Page>\n );\n};\n\nEntityLayout.Route = Route;\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 { catalogApiRef } from '@backstage/plugin-catalog-react';\nimport { Button, Dialog, DialogActions, DialogTitle } from '@material-ui/core';\nimport React, { useState } from 'react';\nimport { alertApiRef, useApi } from '@backstage/core-plugin-api';\nimport { assertError } from '@backstage/errors';\n\ntype Props = {\n open: boolean;\n onClose: () => any;\n onConfirm: () => any;\n entity: Entity;\n};\n\nexport const DeleteEntityDialog = ({\n open,\n onClose,\n onConfirm,\n entity,\n}: Props) => {\n const [busy, setBusy] = useState(false);\n const catalogApi = useApi(catalogApiRef);\n const alertApi = useApi(alertApiRef);\n\n const onDelete = async () => {\n setBusy(true);\n try {\n const uid = entity.metadata.uid;\n await catalogApi.removeEntityByUid(uid!);\n onConfirm();\n } catch (err) {\n assertError(err);\n alertApi.post({ message: err.message });\n } finally {\n setBusy(false);\n }\n };\n\n return (\n <Dialog open={open} onClose={onClose}>\n <DialogTitle id=\"responsive-dialog-title\">\n Are you sure you want to delete this entity?\n </DialogTitle>\n <DialogActions>\n <Button\n variant=\"contained\"\n color=\"secondary\"\n disabled={busy}\n onClick={onDelete}\n >\n Delete\n </Button>\n <Button onClick={onClose} color=\"primary\">\n Cancel\n </Button>\n </DialogActions>\n </Dialog>\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 { catalogRouteRef, useEntity } from '@backstage/plugin-catalog-react';\nimport { Alert } from '@material-ui/lab';\nimport React, { useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { DeleteEntityDialog } from './DeleteEntityDialog';\nimport { useRouteRef } from '@backstage/core-plugin-api';\n\nexport const isOrphan = (entity: Entity) =>\n entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true';\n\n/**\n * Displays a warning alert if the entity is marked as orphan with the ability to delete said entity.\n */\nexport const EntityOrphanWarning = () => {\n const navigate = useNavigate();\n const catalogLink = useRouteRef(catalogRouteRef);\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const { entity } = useEntity();\n\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n navigate(catalogLink());\n };\n\n return (\n <>\n <Alert severity=\"warning\" onClick={() => setConfirmationDialogOpen(true)}>\n This entity is not referenced by any location and is therefore not\n receiving updates. Click here to delete.\n </Alert>\n <DeleteEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\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 {\n Entity,\n AlphaEntity,\n stringifyEntityRef,\n EntityStatusItem,\n compareEntityToRef,\n} from '@backstage/catalog-model';\nimport {\n catalogApiRef,\n EntityRefLink,\n useEntity,\n} from '@backstage/plugin-catalog-react';\nimport { Box } from '@material-ui/core';\nimport React from 'react';\nimport { ResponseErrorPanel } from '@backstage/core-components';\nimport {\n CatalogApi,\n ENTITY_STATUS_CATALOG_PROCESSING_TYPE,\n} from '@backstage/catalog-client';\nimport { useApi, ApiHolder } from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\nimport { SerializedError } from '@backstage/errors';\n\nconst errorFilter = (i: EntityStatusItem) =>\n i.error &&\n i.level === 'error' &&\n i.type === ENTITY_STATUS_CATALOG_PROCESSING_TYPE;\n\ntype GetOwnAndAncestorsErrorsResponse = {\n items: {\n errors: SerializedError[];\n entity: Entity;\n }[];\n};\n\nasync function getOwnAndAncestorsErrors(\n entityRef: string,\n catalogApi: CatalogApi,\n): Promise<GetOwnAndAncestorsErrorsResponse> {\n const ancestors = await catalogApi.getEntityAncestors({ entityRef });\n const items = ancestors.items\n .map(item => {\n const statuses = (item.entity as AlphaEntity).status?.items ?? [];\n const errors = statuses\n .filter(errorFilter)\n .map(e => e.error)\n .filter((e): e is SerializedError => Boolean(e));\n return { errors: errors, entity: item.entity };\n })\n .filter(item => item.errors.length > 0);\n return { items };\n}\n\nexport const hasCatalogProcessingErrors = async (\n entity: Entity,\n context: { apis: ApiHolder },\n) => {\n const catalogApi = context.apis.get(catalogApiRef);\n if (!catalogApi) {\n throw new Error(`No implementation available for ${catalogApiRef}`);\n }\n\n const errors = await getOwnAndAncestorsErrors(\n stringifyEntityRef(entity),\n catalogApi,\n );\n return errors.items.length > 0;\n};\n\n/**\n * Displays a list of errors from the ancestors of the current entity.\n */\nexport const EntityProcessingErrorsPanel = () => {\n const { entity } = useEntity();\n const entityRef = stringifyEntityRef(entity);\n const catalogApi = useApi(catalogApiRef);\n const { loading, error, value } = useAsync(async () => {\n return getOwnAndAncestorsErrors(entityRef, catalogApi);\n }, [entityRef, catalogApi]);\n\n if (error) {\n return (\n <Box mb={1}>\n <ResponseErrorPanel error={error} />\n </Box>\n );\n }\n\n if (loading || !value) {\n return null;\n }\n\n return (\n <>\n {value.items.map((ancestorError, index) => (\n <Box key={index} mb={1}>\n {!compareEntityToRef(\n entity,\n stringifyEntityRef(ancestorError.entity),\n ) && (\n <Box p={1}>\n The error below originates from{' '}\n <EntityRefLink entityRef={ancestorError.entity} />\n </Box>\n )}\n {ancestorError.errors.map((e, i) => (\n <ResponseErrorPanel key={i} error={e} />\n ))}\n </Box>\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 */\nimport React from 'react';\nimport {\n useParams,\n useNavigate,\n PartialRouteObject,\n matchRoutes,\n RouteObject,\n useRoutes,\n Navigate,\n RouteMatch,\n} from 'react-router';\nimport { Helmet } from 'react-helmet';\nimport { Tab, HeaderTabs, Content } from '@backstage/core-components';\n\nconst getSelectedIndexOrDefault = (\n matchedRoute: RouteMatch,\n tabs: Tab[],\n defaultIndex = 0,\n) => {\n if (!matchedRoute) return defaultIndex;\n const tabIndex = tabs.findIndex(t => t.id === matchedRoute.route.path);\n return ~tabIndex ? tabIndex : defaultIndex;\n};\n\n/**\n * Compound component, which allows you to define layout\n * for EntityPage using Tabs as a sub-navigation mechanism\n * Consists of 2 parts: Tabbed.Layout and Tabbed.Content.\n * Takes care of: tabs, routes, document titles, spacing around content\n *\n * @example\n * ```jsx\n * <Tabbed.Layout>\n * <Tabbed.Content\n * title=\"Example tab\"\n * route=\"/example/*\"\n * element={<div>This is rendered under /example/anything-here route</div>}\n * />\n * </TabbedLayout>\n * ```\n */\nexport const Tabbed = {\n Layout: ({ children }: { children: React.ReactNode }) => {\n const routes: PartialRouteObject[] = [];\n const tabs: Tab[] = [];\n const params = useParams();\n const navigate = useNavigate();\n\n React.Children.forEach(children, child => {\n if (!React.isValidElement(child)) {\n // Skip conditionals resolved to falses/nulls/undefineds etc\n return;\n }\n if (child.type !== Tabbed.Content) {\n throw new Error(\n 'This component only accepts Content elements as direct children. Check the code of the EntityPage.',\n );\n }\n const pathAndId = (child as JSX.Element).props.path;\n\n // Child here must be then always a functional component without any wrappers\n tabs.push({\n id: pathAndId,\n label: (child as JSX.Element).props.title,\n });\n\n routes.push({\n path: pathAndId,\n element: child.props.element,\n });\n });\n\n // Add catch-all for incorrect sub-routes\n if ((routes?.[0]?.path ?? '') !== '')\n routes.push({\n path: '/*',\n element: <Navigate to={routes[0].path!} />,\n });\n\n const [matchedRoute] =\n matchRoutes(routes as RouteObject[], `/${params['*']}`) ?? [];\n const selectedIndex = getSelectedIndexOrDefault(matchedRoute, tabs);\n const currentTab = tabs[selectedIndex];\n const title = currentTab?.label;\n\n const onTabChange = (index: number) =>\n // Remove trailing /*\n // And remove leading / for relative navigation\n // Note! route resolves relative to the position in the React tree,\n // not relative to current location\n navigate(tabs[index].id.replace(/\\/\\*$/, '').replace(/^\\//, ''));\n\n const currentRouteElement = useRoutes(routes);\n\n if (!currentTab) return null;\n return (\n <>\n <HeaderTabs\n tabs={tabs}\n selectedIndex={selectedIndex}\n onChange={onTabChange}\n />\n <Content>\n <Helmet title={title} />\n {currentRouteElement}\n </Content>\n </>\n );\n },\n Content: (_props: { path: string; title: string; element: JSX.Element }) =>\n null,\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 {\n Entity,\n ENTITY_DEFAULT_NAMESPACE,\n RELATION_OWNED_BY,\n} from '@backstage/catalog-model';\nimport {\n EntityContext,\n EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n UnregisterEntityDialog,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box } from '@material-ui/core';\nimport React, { useContext, useState } from 'react';\nimport { useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\nimport { Tabbed } from './Tabbed';\n\nimport {\n Content,\n Header,\n HeaderLabel,\n Link,\n Page,\n Progress,\n ResponseErrorPanel,\n WarningPanel,\n} from '@backstage/core-components';\n\nimport { IconComponent } from '@backstage/core-plugin-api';\n\nconst EntityPageTitle = ({\n entity,\n title,\n}: {\n title: string;\n entity: Entity | undefined;\n}) => (\n <Box display=\"inline-flex\" alignItems=\"center\" height=\"1em\">\n {title}\n {entity && <FavoriteEntity entity={entity} />}\n </Box>\n);\n\nconst EntityLabels = ({ entity }: { entity: Entity }) => {\n const ownedByRelations = getEntityRelations(entity, RELATION_OWNED_BY);\n return (\n <>\n {ownedByRelations.length > 0 && (\n <HeaderLabel\n label=\"Owner\"\n value={\n <EntityRefLinks\n entityRefs={ownedByRelations}\n defaultKind=\"Group\"\n color=\"inherit\"\n />\n }\n />\n )}\n {entity.spec?.lifecycle && (\n <HeaderLabel label=\"Lifecycle\" value={entity.spec.lifecycle} />\n )}\n </>\n );\n};\n\nconst headerProps = (\n kind: string,\n namespace: string | undefined,\n name: string,\n entity: Entity | undefined,\n): { headerTitle: string; headerType: string } => {\n return {\n headerTitle: `${name}${\n namespace && namespace !== ENTITY_DEFAULT_NAMESPACE\n ? ` in ${namespace}`\n : ''\n }`,\n headerType: (() => {\n let t = kind.toLocaleLowerCase('en-US');\n if (entity && entity.spec && 'type' in entity.spec) {\n t += ' — ';\n t += (entity.spec as { type: string }).type.toLocaleLowerCase('en-US');\n }\n return t;\n })(),\n };\n};\n\n// NOTE(freben): Intentionally not exported at this point, since it's part of\n// the unstable extra context menu items concept below\ntype ExtraContextMenuItem = {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n};\n\n// unstable context menu option, eg: disable the unregister entity menu\ntype contextMenuOptions = {\n disableUnregister: boolean;\n};\n\ntype EntityPageLayoutProps = {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n children?: React.ReactNode;\n};\n\nexport const EntityPageLayout = ({\n children,\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n}: EntityPageLayoutProps) => {\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useContext(EntityContext);\n const { headerTitle, headerType } = headerProps(\n kind,\n namespace,\n name,\n entity!,\n );\n\n const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);\n const navigate = useNavigate();\n const cleanUpAfterRemoval = async () => {\n setConfirmationDialogOpen(false);\n navigate('/');\n };\n\n const showRemovalDialog = () => setConfirmationDialogOpen(true);\n\n return (\n <Page themeId={entity?.spec?.type?.toString() ?? 'home'}>\n <Header\n title={<EntityPageTitle title={headerTitle} entity={entity!} />}\n pageTitleOverride={headerTitle}\n type={headerType}\n >\n {/* TODO: Make entity labels configurable for entity kind / type */}\n {entity && (\n <>\n <EntityLabels entity={entity} />\n <EntityContextMenu\n UNSTABLE_extraContextMenuItems={UNSTABLE_extraContextMenuItems}\n UNSTABLE_contextMenuOptions={UNSTABLE_contextMenuOptions}\n onUnregisterEntity={showRemovalDialog}\n />\n </>\n )}\n </Header>\n\n {loading && (\n <Content>\n <Progress />\n </Content>\n )}\n\n {entity && <Tabbed.Layout>{children}</Tabbed.Layout>}\n\n {error && (\n <Content>\n <ResponseErrorPanel error={error} />\n </Content>\n )}\n\n {!loading && !error && !entity && (\n <Content>\n <WarningPanel title=\"Entity not found\">\n There is no {kind} with the requested{' '}\n <Link to=\"https://backstage.io/docs/features/software-catalog/references\">\n kind, namespace, and name\n </Link>\n .\n </WarningPanel>\n </Content>\n )}\n\n <UnregisterEntityDialog\n open={confirmationDialogOpen}\n entity={entity!}\n onConfirm={cleanUpAfterRemoval}\n onClose={() => setConfirmationDialogOpen(false)}\n />\n </Page>\n );\n};\n\nEntityPageLayout.Content = Tabbed.Content;\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 { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport React, { PropsWithChildren, ReactNode } from 'react';\nimport {\n attachComponentData,\n useApiHolder,\n useElementFilter,\n ApiHolder,\n} from '@backstage/core-plugin-api';\nimport useAsync from 'react-use/lib/useAsync';\n\nconst ENTITY_SWITCH_KEY = 'core.backstage.entitySwitch';\n\nconst EntitySwitchCase = (_: {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: ReactNode;\n}) => null;\n\nattachComponentData(EntitySwitchCase, ENTITY_SWITCH_KEY, true);\n\ntype SwitchCase = {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: JSX.Element;\n};\n\ntype SwitchCaseResult = {\n if: boolean | Promise<boolean>;\n children: JSX.Element;\n};\n\nexport const EntitySwitch = ({ children }: PropsWithChildren<{}>) => {\n const { entity } = useEntity();\n const apis = useApiHolder();\n const results = useElementFilter(\n children,\n collection =>\n collection\n .selectByComponentData({\n key: ENTITY_SWITCH_KEY,\n withStrictError: 'Child of EntitySwitch is not an EntitySwitch.Case',\n })\n .getElements()\n .flatMap<SwitchCaseResult>((element: React.ReactElement) => {\n const { if: condition, children: elementsChildren } =\n element.props as SwitchCase;\n return [\n {\n if: condition?.(entity, { apis }) ?? true,\n children: elementsChildren,\n },\n ];\n }),\n [apis, entity],\n );\n const hasAsyncCases = results.some(\n r => typeof r.if === 'object' && 'then' in r.if,\n );\n\n if (hasAsyncCases) {\n return <AsyncEntitySwitch results={results} />;\n }\n\n return results.find(r => r.if)?.children ?? null;\n};\n\nfunction AsyncEntitySwitch({ results }: { results: SwitchCaseResult[] }) {\n const { loading, value } = useAsync(async () => {\n const promises = results.map(\n async ({ if: condition, children: output }) => {\n try {\n if (await condition) {\n return output;\n }\n } catch {\n /* ignored */\n }\n\n return null;\n },\n );\n return (await Promise.all(promises)).find(Boolean) ?? null;\n }, [results]);\n\n if (loading || !value) {\n return null;\n }\n\n return value;\n}\n\nEntitySwitch.Case = EntitySwitchCase;\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 { Entity, ComponentEntity } from '@backstage/catalog-model';\n\nfunction strCmp(a: string | undefined, b: string | undefined): boolean {\n return Boolean(\n a && a?.toLocaleLowerCase('en-US') === b?.toLocaleLowerCase('en-US'),\n );\n}\n\nexport function isKind(kind: string) {\n return (entity: Entity) => strCmp(entity?.kind, kind);\n}\n\nexport function isComponentType(type: string) {\n return (entity: Entity) => {\n if (!strCmp(entity?.kind, 'component')) {\n return false;\n }\n const componentEntity = entity as ComponentEntity;\n return strCmp(componentEntity.spec.type, type);\n };\n}\n\nexport function isNamespace(namespace: string) {\n return (entity: Entity) => strCmp(entity?.metadata?.namespace, namespace);\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 { Grid } from '@material-ui/core';\nimport React, { PropsWithChildren } from 'react';\n\nexport const FilteredEntityLayout = ({ children }: PropsWithChildren<{}>) => (\n <Grid container style={{ position: 'relative' }}>\n {children}\n </Grid>\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 { BackstageTheme } from '@backstage/theme';\nimport {\n Box,\n Button,\n Drawer,\n Grid,\n Typography,\n useMediaQuery,\n useTheme,\n} from '@material-ui/core';\nimport FilterListIcon from '@material-ui/icons/FilterList';\nimport React, { useState, PropsWithChildren } from 'react';\n\nexport const FilterContainer = ({ children }: PropsWithChildren<{}>) => {\n const isMidSizeScreen = useMediaQuery<BackstageTheme>(theme =>\n theme.breakpoints.down('md'),\n );\n const theme = useTheme<BackstageTheme>();\n const [filterDrawerOpen, setFilterDrawerOpen] = useState<boolean>(false);\n\n return isMidSizeScreen ? (\n <>\n <Button\n style={{ marginTop: theme.spacing(1), marginLeft: theme.spacing(1) }}\n onClick={() => setFilterDrawerOpen(true)}\n startIcon={<FilterListIcon />}\n >\n Filters\n </Button>\n <Drawer\n open={filterDrawerOpen}\n onClose={() => setFilterDrawerOpen(false)}\n anchor=\"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 Filters\n </Typography>\n {children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {children}\n </Grid>\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 { Grid } from '@material-ui/core';\nimport React, { PropsWithChildren } from 'react';\n\nexport const EntityListContainer = ({ children }: PropsWithChildren<{}>) => (\n <Grid item xs={12} lg={10}>\n {children}\n </Grid>\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 Content,\n ContentHeader,\n CreateButton,\n PageWithHeader,\n SupportButton,\n TableColumn,\n TableProps,\n} from '@backstage/core-components';\nimport { configApiRef, useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport {\n EntityLifecyclePicker,\n EntityListProvider,\n EntityOwnerPicker,\n EntityTagPicker,\n EntityTypePicker,\n UserListFilterKind,\n UserListPicker,\n} from '@backstage/plugin-catalog-react';\nimport React from 'react';\nimport { createComponentRouteRef } from '../../routes';\nimport { CatalogTable } from '../CatalogTable';\nimport { EntityRow } from '../CatalogTable/types';\nimport {\n FilteredEntityLayout,\n EntityListContainer,\n FilterContainer,\n} from '../FilteredEntityLayout';\nimport { CatalogKindHeader } from '../CatalogKindHeader';\n\n/**\n * DefaultCatalogPageProps\n * @public\n */\nexport type DefaultCatalogPageProps = {\n initiallySelectedFilter?: UserListFilterKind;\n columns?: TableColumn<EntityRow>[];\n actions?: TableProps<EntityRow>['actions'];\n};\n\nexport const DefaultCatalogPage = ({\n columns,\n actions,\n initiallySelectedFilter = 'owned',\n}: DefaultCatalogPageProps) => {\n const orgName =\n useApi(configApiRef).getOptionalString('organization.name') ?? 'Backstage';\n const createComponentLink = useRouteRef(createComponentRouteRef);\n\n return (\n <PageWithHeader title={`${orgName} Catalog`} themeId=\"home\">\n <EntityListProvider>\n <Content>\n <ContentHeader titleComponent={<CatalogKindHeader />}>\n <CreateButton\n title=\"Create Component\"\n to={createComponentLink && createComponentLink()}\n />\n <SupportButton>All your software catalog entities</SupportButton>\n </ContentHeader>\n <FilteredEntityLayout>\n <FilterContainer>\n <EntityTypePicker />\n <UserListPicker initialFilter={initiallySelectedFilter} />\n <EntityOwnerPicker />\n <EntityLifecyclePicker />\n <EntityTagPicker />\n </FilterContainer>\n <EntityListContainer>\n <CatalogTable columns={columns} actions={actions} />\n </EntityListContainer>\n </FilteredEntityLayout>\n </Content>\n </EntityListProvider>\n </PageWithHeader>\n );\n};\n","/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { useOutlet } from 'react-router';\nimport {\n DefaultCatalogPage,\n DefaultCatalogPageProps,\n} from './DefaultCatalogPage';\n\nexport const CatalogPage = (props: DefaultCatalogPageProps) => {\n const outlet = useOutlet();\n\n return outlet || <DefaultCatalogPage {...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 React from 'react';\nimport { makeStyles } from '@material-ui/core';\nimport IlloSvgUrl from './illo.svg';\n\nconst useStyles = makeStyles(theme => ({\n illo: {\n maxWidth: '60%',\n top: 100,\n right: 20,\n position: 'absolute',\n [theme.breakpoints.down('xs')]: {\n maxWidth: '96%',\n position: 'relative',\n top: 'unset',\n right: 'unset',\n margin: `${theme.spacing(10)}px auto ${theme.spacing(4)}px`,\n },\n },\n}));\n\nexport const Illo = () => {\n const classes = useStyles();\n return (\n <img\n src={IlloSvgUrl}\n className={classes.illo}\n alt=\"Illustration on entity not found page\"\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 React from 'react';\nimport { Grid, Button, Typography } from '@material-ui/core';\nimport { makeStyles } from '@material-ui/core/styles';\nimport { BackstageTheme } from '@backstage/theme';\n\nimport { Illo } from './Illo';\n\nconst useStyles = makeStyles<BackstageTheme>(theme => ({\n container: {\n paddingTop: theme.spacing(24),\n paddingLeft: theme.spacing(8),\n [theme.breakpoints.down('xs')]: {\n padding: theme.spacing(2),\n },\n },\n title: {\n paddingBottom: theme.spacing(2),\n [theme.breakpoints.down('xs')]: {\n fontSize: 32,\n },\n },\n body: {\n paddingBottom: theme.spacing(6),\n [theme.breakpoints.down('xs')]: {\n paddingBottom: theme.spacing(5),\n },\n },\n}));\n\nexport const EntityNotFound = () => {\n const classes = useStyles();\n\n return (\n <Grid container spacing={0} className={classes.container}>\n <Illo />\n <Grid item xs={12} sm={6}>\n <Typography variant=\"h2\" className={classes.title}>\n Entity was not found\n </Typography>\n <Typography variant=\"body1\" className={classes.body}>\n Want to help us build this? Check out our Getting Started\n documentation.\n </Typography>\n <Button\n variant=\"contained\"\n color=\"primary\"\n href=\"https://backstage.io/docs\"\n >\n DOCS\n </Button>\n </Grid>\n </Grid>\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 { ENTITY_DEFAULT_NAMESPACE } from '@backstage/catalog-model';\nimport {\n AsyncEntityProvider,\n useEntity,\n useEntityFromUrl,\n} from '@backstage/plugin-catalog-react';\nimport { Typography } from '@material-ui/core';\nimport React, { ComponentType, ReactNode } from 'react';\nimport { Navigate, Route, Routes, useParams } from 'react-router';\nimport { CatalogPage } from './CatalogPage';\nimport { EntityNotFound } from './EntityNotFound';\nimport { EntityPageLayout } from './EntityPageLayout';\nimport { Content, Link } from '@backstage/core-components';\n\nconst DefaultEntityPage = () => (\n <EntityPageLayout>\n <EntityPageLayout.Content\n path=\"/\"\n title=\"Overview\"\n element={\n <Content>\n <Typography variant=\"h2\">This is the default entity page.</Typography>\n <Typography variant=\"body1\">\n To override this component with your custom implementation, read\n docs on{' '}\n <Link to=\"https://backstage.io/docs\">backstage.io/docs</Link>\n </Typography>\n </Content>\n }\n />\n </EntityPageLayout>\n);\n\nconst EntityPageSwitch = ({ EntityPage }: { EntityPage: ComponentType }) => {\n const { entity, loading, error } = useEntity();\n // Loading and error states\n if (loading) return <EntityPageLayout />;\n if (error || !entity) return <EntityNotFound />;\n\n // Otherwise EntityPage provided from the App\n // Note that EntityPage will include EntityPageLayout already\n return <EntityPage />;\n};\n\nconst OldEntityRouteRedirect = () => {\n const { optionalNamespaceAndName, '*': rest } = useParams() as any;\n const [name, namespace] = optionalNamespaceAndName.split(':').reverse();\n const namespaceLower =\n namespace?.toLocaleLowerCase('en-US') ?? ENTITY_DEFAULT_NAMESPACE;\n const restWithSlash = rest ? `/${rest}` : '';\n return (\n <Navigate\n to={`../../${namespaceLower}/component/${name}${restWithSlash}`}\n />\n );\n};\n\nexport const EntityLoader = (props: { children: ReactNode }) => (\n <AsyncEntityProvider {...useEntityFromUrl()} {...props} />\n);\n\n/**\n * @deprecated Use plugin extensions instead\n * */\nexport const Router = ({\n EntityPage = DefaultEntityPage,\n}: {\n EntityPage?: ComponentType;\n}) => (\n <Routes>\n <Route path=\"/\" element={<CatalogPage />} />\n <Route\n path=\"/:namespace/:kind/:name\"\n element={\n <EntityLoader>\n <EntityPageSwitch EntityPage={EntityPage} />\n </EntityLoader>\n }\n />\n <Route\n path=\"Component/:optionalNamespaceAndName/*\"\n element={<OldEntityRouteRedirect />}\n />\n </Routes>\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 { CatalogClient } from '@backstage/catalog-client';\nimport {\n catalogApiRef,\n catalogRouteRef,\n DefaultStarredEntitiesApi,\n entityRouteRef,\n starredEntitiesApiRef,\n} from '@backstage/plugin-catalog-react';\nimport { createComponentRouteRef, viewTechDocRouteRef } from './routes';\nimport {\n createApiFactory,\n createComponentExtension,\n createPlugin,\n createRoutableExtension,\n discoveryApiRef,\n fetchApiRef,\n storageApiRef,\n} from '@backstage/core-plugin-api';\n\nexport const catalogPlugin = createPlugin({\n id: 'catalog',\n apis: [\n createApiFactory({\n api: catalogApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ discoveryApi, fetchApi }) =>\n new CatalogClient({ discoveryApi, fetchApi }),\n }),\n createApiFactory({\n api: starredEntitiesApiRef,\n deps: { storageApi: storageApiRef },\n factory: ({ storageApi }) =>\n new DefaultStarredEntitiesApi({ storageApi }),\n }),\n ],\n routes: {\n catalogIndex: catalogRouteRef,\n catalogEntity: entityRouteRef,\n },\n externalRoutes: {\n createComponent: createComponentRouteRef,\n viewTechDoc: viewTechDocRouteRef,\n },\n});\n\nexport const CatalogIndexPage = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogIndexPage',\n component: () =>\n import('./components/CatalogPage').then(m => m.CatalogPage),\n mountPoint: catalogRouteRef,\n }),\n);\n\nexport const CatalogEntityPage = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogEntityPage',\n component: () =>\n import('./components/CatalogEntityPage').then(m => m.CatalogEntityPage),\n mountPoint: entityRouteRef,\n }),\n);\n\nexport const EntityAboutCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityAboutCard',\n component: {\n lazy: () => import('./components/AboutCard').then(m => m.AboutCard),\n },\n }),\n);\n\nexport const EntityLinksCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityLinksCard',\n component: {\n lazy: () =>\n import('./components/EntityLinksCard').then(m => m.EntityLinksCard),\n },\n }),\n);\n\nexport const EntityHasSystemsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSystemsCard',\n component: {\n lazy: () =>\n import('./components/HasSystemsCard').then(m => m.HasSystemsCard),\n },\n }),\n);\n\nexport const EntityHasComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasComponentsCard',\n component: {\n lazy: () =>\n import('./components/HasComponentsCard').then(m => m.HasComponentsCard),\n },\n }),\n);\n\nexport const EntityHasSubcomponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSubcomponentsCard',\n component: {\n lazy: () =>\n import('./components/HasSubcomponentsCard').then(\n m => m.HasSubcomponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityHasResourcesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasResourcesCard',\n component: {\n lazy: () =>\n import('./components/HasResourcesCard').then(m => m.HasResourcesCard),\n },\n }),\n);\n\nexport const EntityDependsOnComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependsOnComponentsCard').then(\n m => m.DependsOnComponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityDependencyOfComponentsCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependencyOfComponentsCard',\n component: {\n lazy: () =>\n import('./components/DependencyOfComponentsCard').then(\n m => m.DependencyOfComponentsCard,\n ),\n },\n }),\n);\n\nexport const EntityDependsOnResourcesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityDependsOnResourcesCard',\n component: {\n lazy: () =>\n import('./components/DependsOnResourcesCard').then(\n m => m.DependsOnResourcesCard,\n ),\n },\n }),\n);\n\n/**\n * @deprecated This component is replaced by EntityCatalogGraphCard which is imported from `@backstage/plugin-catalog-graph`. This component will be removed in an\n * upcoming release\n */\nexport const EntitySystemDiagramCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntitySystemDiagramCard',\n component: {\n lazy: () =>\n import('./components/SystemDiagramCard').then(m => m.SystemDiagramCard),\n },\n }),\n);\n\nexport const RelatedEntitiesCard = catalogPlugin.provide(\n createComponentExtension({\n name: 'RelatedEntitiesCard',\n component: {\n lazy: () =>\n import('./components/RelatedEntitiesCard').then(\n m => m.RelatedEntitiesCard,\n ),\n },\n }),\n);\n"],"names":["useStyles","columnFactories.createNameColumn","columnFactories.createSystemColumn","columnFactories.createOwnerColumn","columnFactories.createSpecTypeColumn","columnFactories.createSpecLifecycleColumn","columnFactories.createMetadataDescriptionColumn","columnFactories.createTagsColumn","capitalize","Edit","makeStyles","headerProps","EntityLabels","Route"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-a41d9b20.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;"}