@backstage/plugin-catalog 0.9.0 → 0.9.1

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,31 @@
1
1
  # @backstage/plugin-catalog
2
2
 
3
+ ## 0.9.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 899f196af5: Use `getEntityByRef` instead of `getEntityByName` in the catalog client
8
+ - f41a293231: - **DEPRECATION**: Deprecated `formatEntityRefTitle` in favor of the new `humanizeEntityRef` method instead. Please migrate to using the new method instead.
9
+ - f590d1681b: Removed usage of deprecated favorite utility methods.
10
+ - 44403296e7: Added the following deprecations to the `catalog-react` package:
11
+
12
+ - **DEPRECATION**: `useEntity` will now warn if the entity has not yet been loaded, and will soon throw errors instead. If you're using the default implementation of `EntityLayout` and `EntitySwitch` then these components will ensure that there is an entity loaded before rendering children. If you're implementing your own `EntityLayout` or `EntitySwitch` or something that operates outside or adjacent to them, then use `useAsyncEntity`.
13
+
14
+ - **DEPRECATION**: the `loading`, `error` and `refresh` properties that are returned from `useEntity` have been deprecated, and are available on `useAsyncEntity` instead.
15
+
16
+ - da79aac2a6: - Replaced usage of the deprecated and now removed `rootRoute` and `catalogRouteRef`s from the `catalog-react` package
17
+ - 36aa63022b: Use `CompoundEntityRef` instead of `EntityName`, and `getCompoundEntityRef` instead of `getEntityName`, from `@backstage/catalog-model`.
18
+ - 8f0e8e039b: Removed usage of deprecated `getEntityMetadataViewUrl` and `getEntityMetadataEditUrl` helpers.
19
+ - Updated dependencies
20
+ - @backstage/catalog-model@0.12.0
21
+ - @backstage/catalog-client@0.8.0
22
+ - @backstage/core-components@0.9.0
23
+ - @backstage/plugin-catalog-react@0.8.0
24
+ - @backstage/plugin-catalog-common@0.2.0
25
+ - @backstage/core-plugin-api@0.8.0
26
+ - @backstage/search-common@0.3.0
27
+ - @backstage/integration-react@0.1.24
28
+
3
29
  ## 0.9.0
4
30
 
5
31
  ### Minor Changes
@@ -1,8 +1,10 @@
1
- import { RELATION_PART_OF, RELATION_OWNED_BY, DEFAULT_NAMESPACE, ANNOTATION_LOCATION, stringifyEntityRef } from '@backstage/catalog-model';
1
+ import ObservableImpl from 'zen-observable';
2
+ import { stringifyEntityRef, RELATION_PART_OF, RELATION_OWNED_BY, ANNOTATION_EDIT_URL, DEFAULT_NAMESPACE, ANNOTATION_LOCATION, ANNOTATION_VIEW_URL } from '@backstage/catalog-model';
3
+ import { isArray, isString, capitalize as capitalize$1 } from 'lodash';
2
4
  import { Link, HeaderIconLinkRow, OverflowTooltip, WarningPanel, CodeSnippet, Table, Page, Header, Progress, RoutedTabs, Content, HeaderLabel, ResponseErrorPanel } from '@backstage/core-components';
3
- import { createExternalRouteRef, useElementFilter, useApi, alertApiRef, useRouteRef, attachComponentData, useApiHolder, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, storageApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
5
+ import { createExternalRouteRef, createRouteRef, useElementFilter, useApi, alertApiRef, useRouteRef, attachComponentData, useApiHolder, createPlugin, createApiFactory, discoveryApiRef, fetchApiRef, storageApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
4
6
  import { scmIntegrationsApiRef, ScmIntegrationIcon } from '@backstage/integration-react';
5
- import { getEntityRelations, EntityRefLinks, useEntity, catalogApiRef, getEntitySourceLocation, getEntityMetadataEditUrl, useEntityList, EntityKindFilter, formatEntityRefTitle, EntityRefLink, useStarredEntities, getEntityMetadataViewUrl, favoriteEntityIcon, favoriteEntityTooltip, useEntityPermission, useEntityCompoundName, UnregisterEntityDialog, InspectEntityDialog, FavoriteEntity, catalogRouteRef, starredEntitiesApiRef, DefaultStarredEntitiesApi, entityRouteRef } from '@backstage/plugin-catalog-react';
7
+ import { getEntityRelations, EntityRefLinks, useEntity, catalogApiRef, getEntitySourceLocation, useEntityList, EntityKindFilter, humanizeEntityRef, EntityRefLink, useStarredEntities, useEntityPermission, useEntityCompoundName, useAsyncEntity, UnregisterEntityDialog, InspectEntityDialog, FavoriteEntity, starredEntitiesApiRef, entityRouteRef } from '@backstage/plugin-catalog-react';
6
8
  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
9
  import CachedIcon from '@material-ui/icons/Cached';
8
10
  import DocsIcon from '@material-ui/icons/Description';
@@ -10,10 +12,11 @@ import EditIcon from '@material-ui/icons/Edit';
10
12
  import React, { useCallback, useState, useEffect, useMemo } from 'react';
11
13
  import useAsync from 'react-use/lib/useAsync';
12
14
  import OpenInNew from '@material-ui/icons/OpenInNew';
13
- import { capitalize as capitalize$1 } from 'lodash';
15
+ import StarBorder from '@material-ui/icons/StarBorder';
16
+ import { withStyles, makeStyles as makeStyles$1 } from '@material-ui/core/styles';
17
+ import Star from '@material-ui/icons/Star';
14
18
  import { Alert } from '@material-ui/lab';
15
19
  import { useLocation, useNavigate } from 'react-router';
16
- import { makeStyles as makeStyles$1 } from '@material-ui/core/styles';
17
20
  import CancelIcon from '@material-ui/icons/Cancel';
18
21
  import BugReportIcon from '@material-ui/icons/BugReport';
19
22
  import MoreVert from '@material-ui/icons/MoreVert';
@@ -22,6 +25,62 @@ import { assertError } from '@backstage/errors';
22
25
  import { ENTITY_STATUS_CATALOG_PROCESSING_TYPE, CatalogClient } from '@backstage/catalog-client';
23
26
  import FilterListIcon from '@material-ui/icons/FilterList';
24
27
 
28
+ async function performMigrationToTheNewBucket({
29
+ storageApi
30
+ }) {
31
+ var _a;
32
+ const source = storageApi.forBucket("settings");
33
+ const target = storageApi.forBucket("starredEntities");
34
+ const oldStarredEntities = source.snapshot("starredEntities").value;
35
+ if (!isArray(oldStarredEntities)) {
36
+ return;
37
+ }
38
+ const targetEntities = new Set((_a = target.snapshot("entityRefs").value) != null ? _a : []);
39
+ oldStarredEntities.filter(isString).map((old) => old.split(":")).filter((split) => split.length === 4 && split[0] === "entity").map(([_, kind, namespace, name]) => stringifyEntityRef({ kind, namespace, name })).forEach((e) => targetEntities.add(e));
40
+ await target.set("entityRefs", Array.from(targetEntities));
41
+ await source.remove("starredEntities");
42
+ }
43
+
44
+ class DefaultStarredEntitiesApi {
45
+ constructor(opts) {
46
+ this.subscribers = /* @__PURE__ */ new Set();
47
+ this.observable = new ObservableImpl((subscriber) => {
48
+ subscriber.next(new Set(this.starredEntities));
49
+ this.subscribers.add(subscriber);
50
+ return () => {
51
+ this.subscribers.delete(subscriber);
52
+ };
53
+ });
54
+ var _a;
55
+ performMigrationToTheNewBucket(opts).then();
56
+ this.settingsStore = opts.storageApi.forBucket("starredEntities");
57
+ this.starredEntities = new Set((_a = this.settingsStore.snapshot("entityRefs").value) != null ? _a : []);
58
+ this.settingsStore.observe$("entityRefs").subscribe({
59
+ next: (next) => {
60
+ var _a2;
61
+ this.starredEntities = new Set((_a2 = next.value) != null ? _a2 : []);
62
+ this.notifyChanges();
63
+ }
64
+ });
65
+ }
66
+ async toggleStarred(entityRef) {
67
+ if (this.starredEntities.has(entityRef)) {
68
+ this.starredEntities.delete(entityRef);
69
+ } else {
70
+ this.starredEntities.add(entityRef);
71
+ }
72
+ await this.settingsStore.set("entityRefs", Array.from(this.starredEntities));
73
+ }
74
+ starredEntitie$() {
75
+ return this.observable;
76
+ }
77
+ notifyChanges() {
78
+ for (const subscription of this.subscribers) {
79
+ subscription.next(new Set(this.starredEntities));
80
+ }
81
+ }
82
+ }
83
+
25
84
  const createComponentRouteRef = createExternalRouteRef({
26
85
  id: "create-component",
27
86
  optional: true
@@ -31,6 +90,9 @@ const viewTechDocRouteRef = createExternalRouteRef({
31
90
  optional: true,
32
91
  params: ["namespace", "kind", "name"]
33
92
  });
93
+ const rootRouteRef = createRouteRef({
94
+ id: "catalog"
95
+ });
34
96
 
35
97
  const useStyles$5 = makeStyles((theme) => ({
36
98
  value: {
@@ -168,7 +230,7 @@ const useStyles$3 = makeStyles({
168
230
  }
169
231
  });
170
232
  function AboutCard(props) {
171
- var _a, _b;
233
+ var _a, _b, _c;
172
234
  const { variant } = props;
173
235
  const classes = useStyles$3();
174
236
  const { entity } = useEntity();
@@ -177,7 +239,7 @@ function AboutCard(props) {
177
239
  const alertApi = useApi(alertApiRef);
178
240
  const viewTechdocLink = useRouteRef(viewTechDocRouteRef);
179
241
  const entitySourceLocation = getEntitySourceLocation(entity, scmIntegrationsApi);
180
- const entityMetadataEditUrl = getEntityMetadataEditUrl(entity);
242
+ const entityMetadataEditUrl = (_a = entity.metadata.annotations) == null ? void 0 : _a[ANNOTATION_EDIT_URL];
181
243
  const viewInSource = {
182
244
  label: "View Source",
183
245
  disabled: !entitySourceLocation,
@@ -188,7 +250,7 @@ function AboutCard(props) {
188
250
  };
189
251
  const viewInTechDocs = {
190
252
  label: "View TechDocs",
191
- disabled: !((_a = entity.metadata.annotations) == null ? void 0 : _a["backstage.io/techdocs-ref"]) || !viewTechdocLink,
253
+ disabled: !((_b = entity.metadata.annotations) == null ? void 0 : _b["backstage.io/techdocs-ref"]) || !viewTechdocLink,
192
254
  icon: /* @__PURE__ */ React.createElement(DocsIcon, null),
193
255
  href: viewTechdocLink && viewTechdocLink({
194
256
  namespace: entity.metadata.namespace || DEFAULT_NAMESPACE,
@@ -208,7 +270,7 @@ function AboutCard(props) {
208
270
  } else if (variant === "fullHeight") {
209
271
  cardContentClass = classes.fullHeightCardContent;
210
272
  }
211
- const entityLocation = (_b = entity.metadata.annotations) == null ? void 0 : _b[ANNOTATION_LOCATION];
273
+ const entityLocation = (_c = entity.metadata.annotations) == null ? void 0 : _c[ANNOTATION_LOCATION];
212
274
  const allowRefresh = (entityLocation == null ? void 0 : entityLocation.startsWith("url:")) || (entityLocation == null ? void 0 : entityLocation.startsWith("file:"));
213
275
  const refreshEntity = useCallback(async () => {
214
276
  await catalogApi.refreshEntity(stringifyEntityRef(entity));
@@ -318,7 +380,7 @@ const columnFactories = Object.freeze({
318
380
  createNameColumn(options) {
319
381
  function formatContent(entity) {
320
382
  var _a;
321
- return ((_a = entity.metadata) == null ? void 0 : _a.title) || formatEntityRefTitle(entity, {
383
+ return ((_a = entity.metadata) == null ? void 0 : _a.title) || humanizeEntityRef(entity, {
322
384
  defaultKind: options == null ? void 0 : options.defaultKind
323
385
  });
324
386
  }
@@ -401,6 +463,11 @@ const columnFactories = Object.freeze({
401
463
  }
402
464
  });
403
465
 
466
+ const YellowStar = withStyles({
467
+ root: {
468
+ color: "#f3ba37"
469
+ }
470
+ })(Star);
404
471
  const CatalogTable = (props) => {
405
472
  var _a, _b, _c;
406
473
  const { columns, actions } = props;
@@ -431,7 +498,8 @@ const CatalogTable = (props) => {
431
498
  }
432
499
  const defaultActions = [
433
500
  ({ entity }) => {
434
- const url = getEntityMetadataViewUrl(entity);
501
+ var _a2;
502
+ const url = (_a2 = entity.metadata.annotations) == null ? void 0 : _a2[ANNOTATION_VIEW_URL];
435
503
  return {
436
504
  icon: () => /* @__PURE__ */ React.createElement(OpenInNew, {
437
505
  "aria-label": "View",
@@ -447,7 +515,8 @@ const CatalogTable = (props) => {
447
515
  };
448
516
  },
449
517
  ({ entity }) => {
450
- const url = getEntityMetadataEditUrl(entity);
518
+ var _a2;
519
+ const url = (_a2 = entity.metadata.annotations) == null ? void 0 : _a2[ANNOTATION_EDIT_URL];
451
520
  return {
452
521
  icon: () => /* @__PURE__ */ React.createElement(EditIcon, {
453
522
  "aria-label": "Edit",
@@ -466,8 +535,8 @@ const CatalogTable = (props) => {
466
535
  const isStarred = isStarredEntity(entity);
467
536
  return {
468
537
  cellStyle: { paddingLeft: "1em" },
469
- icon: () => favoriteEntityIcon(isStarred),
470
- tooltip: favoriteEntityTooltip(isStarred),
538
+ icon: () => isStarred ? /* @__PURE__ */ React.createElement(YellowStar, null) : /* @__PURE__ */ React.createElement(StarBorder, null),
539
+ tooltip: isStarred ? "Remove from favorites" : "Add to favorites",
471
540
  onClick: () => toggleStarredEntity(entity)
472
541
  };
473
542
  }
@@ -480,12 +549,12 @@ const CatalogTable = (props) => {
480
549
  return {
481
550
  entity,
482
551
  resolved: {
483
- name: formatEntityRefTitle(entity, {
552
+ name: humanizeEntityRef(entity, {
484
553
  defaultKind: "Component"
485
554
  }),
486
- ownedByRelationsTitle: ownedByRelations.map((r) => formatEntityRefTitle(r, { defaultKind: "group" })).join(", "),
555
+ ownedByRelationsTitle: ownedByRelations.map((r) => humanizeEntityRef(r, { defaultKind: "group" })).join(", "),
487
556
  ownedByRelations,
488
- partOfSystemRelationTitle: partOfSystemRelations.map((r) => formatEntityRefTitle(r, {
557
+ partOfSystemRelationTitle: partOfSystemRelations.map((r) => humanizeEntityRef(r, {
489
558
  defaultKind: "system"
490
559
  })).join(", "),
491
560
  partOfSystemRelations
@@ -651,13 +720,15 @@ const EntityLayout = (props) => {
651
720
  children
652
721
  } = props;
653
722
  const { kind, namespace, name } = useEntityCompoundName();
654
- const { entity, loading, error } = useEntity();
723
+ const { entity, loading, error } = useAsyncEntity();
655
724
  const location = useLocation();
656
725
  const routes = useElementFilter(children, (elements) => elements.selectByComponentData({
657
726
  key: dataKey,
658
727
  withStrictError: "Child of EntityLayout must be an EntityLayout.Route"
659
728
  }).getElements().flatMap(({ props: elementProps }) => {
660
- if (elementProps.if && entity && !elementProps.if(entity)) {
729
+ if (!entity) {
730
+ return [];
731
+ } else if (elementProps.if && !elementProps.if(entity)) {
661
732
  return [];
662
733
  }
663
734
  return [
@@ -759,7 +830,7 @@ function isOrphan(entity) {
759
830
  }
760
831
  function EntityOrphanWarning() {
761
832
  const navigate = useNavigate();
762
- const catalogLink = useRouteRef(catalogRouteRef);
833
+ const catalogLink = useRouteRef(rootRouteRef);
763
834
  const [confirmationDialogOpen, setConfirmationDialogOpen] = useState(false);
764
835
  const { entity } = useEntity();
765
836
  const cleanUpAfterRemoval = async () => {
@@ -831,13 +902,16 @@ const EntitySwitchCaseComponent = (_props) => null;
831
902
  attachComponentData(EntitySwitchCaseComponent, ENTITY_SWITCH_KEY, true);
832
903
  const EntitySwitch = (props) => {
833
904
  var _a, _b;
834
- const { entity } = useEntity();
905
+ const { entity } = useAsyncEntity();
835
906
  const apis = useApiHolder();
836
907
  const results = useElementFilter(props.children, (collection) => collection.selectByComponentData({
837
908
  key: ENTITY_SWITCH_KEY,
838
909
  withStrictError: "Child of EntitySwitch is not an EntitySwitch.Case"
839
910
  }).getElements().flatMap((element) => {
840
911
  var _a2;
912
+ if (!entity) {
913
+ return [];
914
+ }
841
915
  const { if: condition, children: elementsChildren } = element.props;
842
916
  return [
843
917
  {
@@ -879,11 +953,11 @@ function strCmp(a, b) {
879
953
  return Boolean(a && (a == null ? void 0 : a.toLocaleLowerCase("en-US")) === (b == null ? void 0 : b.toLocaleLowerCase("en-US")));
880
954
  }
881
955
  function isKind(kind) {
882
- return (entity) => strCmp(entity == null ? void 0 : entity.kind, kind);
956
+ return (entity) => strCmp(entity.kind, kind);
883
957
  }
884
958
  function isComponentType(type) {
885
959
  return (entity) => {
886
- if (!strCmp(entity == null ? void 0 : entity.kind, "component")) {
960
+ if (!strCmp(entity.kind, "component")) {
887
961
  return false;
888
962
  }
889
963
  const componentEntity = entity;
@@ -893,7 +967,7 @@ function isComponentType(type) {
893
967
  function isNamespace(namespace) {
894
968
  return (entity) => {
895
969
  var _a;
896
- return strCmp((_a = entity == null ? void 0 : entity.metadata) == null ? void 0 : _a.namespace, namespace);
970
+ return strCmp((_a = entity.metadata) == null ? void 0 : _a.namespace, namespace);
897
971
  };
898
972
  }
899
973
 
@@ -957,7 +1031,7 @@ const catalogPlugin = createPlugin({
957
1031
  })
958
1032
  ],
959
1033
  routes: {
960
- catalogIndex: catalogRouteRef,
1034
+ catalogIndex: rootRouteRef,
961
1035
  catalogEntity: entityRouteRef
962
1036
  },
963
1037
  externalRoutes: {
@@ -967,18 +1041,18 @@ const catalogPlugin = createPlugin({
967
1041
  });
968
1042
  const CatalogIndexPage = catalogPlugin.provide(createRoutableExtension({
969
1043
  name: "CatalogIndexPage",
970
- component: () => import('./index-0518ad02.esm.js').then((m) => m.CatalogPage),
971
- mountPoint: catalogRouteRef
1044
+ component: () => import('./index-61fe5994.esm.js').then((m) => m.CatalogPage),
1045
+ mountPoint: rootRouteRef
972
1046
  }));
973
1047
  const CatalogEntityPage = catalogPlugin.provide(createRoutableExtension({
974
1048
  name: "CatalogEntityPage",
975
- component: () => import('./index-7f3caf38.esm.js').then((m) => m.CatalogEntityPage),
1049
+ component: () => import('./index-7e69bc27.esm.js').then((m) => m.CatalogEntityPage),
976
1050
  mountPoint: entityRouteRef
977
1051
  }));
978
1052
  const EntityAboutCard = catalogPlugin.provide(createComponentExtension({
979
1053
  name: "EntityAboutCard",
980
1054
  component: {
981
- lazy: () => import('./index-31a771c4.esm.js').then((m) => m.AboutCard)
1055
+ lazy: () => import('./index-3cf25427.esm.js').then((m) => m.AboutCard)
982
1056
  }
983
1057
  }));
984
1058
  const EntityLinksCard = catalogPlugin.provide(createComponentExtension({
@@ -1036,5 +1110,5 @@ const RelatedEntitiesCard = catalogPlugin.provide(createComponentExtension({
1036
1110
  }
1037
1111
  }));
1038
1112
 
1039
- export { AboutCard as A, isNamespace as B, CatalogKindHeader as C, isComponentType as D, EntityListContainer as E, FilteredEntityLayout as F, RelatedEntitiesCard as R, FilterContainer as a, CatalogTable as b, createComponentRouteRef as c, AboutContent as d, AboutField as e, CatalogEntityPage as f, CatalogIndexPage as g, catalogPlugin as h, EntityAboutCard as i, EntityDependencyOfComponentsCard as j, EntityDependsOnComponentsCard as k, EntityDependsOnResourcesCard as l, EntityHasComponentsCard as m, EntityHasResourcesCard as n, EntityHasSubcomponentsCard as o, EntityHasSystemsCard as p, EntityLinksCard as q, CatalogSearchResultListItem as r, CatalogResultListItem as s, EntityLayout as t, EntityOrphanWarning as u, isOrphan as v, EntityProcessingErrorsPanel as w, hasCatalogProcessingErrors as x, EntitySwitch as y, isKind as z };
1040
- //# sourceMappingURL=index-6ca877bd.esm.js.map
1113
+ export { AboutCard as A, isNamespace as B, CatalogKindHeader as C, DefaultStarredEntitiesApi as D, EntityListContainer as E, FilteredEntityLayout as F, isComponentType as G, RelatedEntitiesCard as R, FilterContainer as a, CatalogTable as b, createComponentRouteRef as c, AboutContent as d, AboutField as e, CatalogEntityPage as f, CatalogIndexPage as g, catalogPlugin as h, EntityAboutCard as i, EntityDependencyOfComponentsCard as j, EntityDependsOnComponentsCard as k, EntityDependsOnResourcesCard as l, EntityHasComponentsCard as m, EntityHasResourcesCard as n, EntityHasSubcomponentsCard as o, EntityHasSystemsCard as p, EntityLinksCard as q, CatalogSearchResultListItem as r, CatalogResultListItem as s, EntityLayout as t, EntityOrphanWarning as u, isOrphan as v, EntityProcessingErrorsPanel as w, hasCatalogProcessingErrors as x, EntitySwitch as y, isKind as z };
1114
+ //# sourceMappingURL=index-1f9336e4.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-1f9336e4.esm.js","sources":["../../src/apis/StarredEntitiesApi/migration.ts","../../src/apis/StarredEntitiesApi/DefaultStarredEntitiesApi.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/CatalogSearchResultListItem/CatalogSearchResultListItem.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/EntitySwitch/EntitySwitch.tsx","../../src/components/EntitySwitch/conditions.ts","../../src/components/FilteredEntityLayout/FilteredEntityLayout.tsx","../../src/components/FilteredEntityLayout/FilterContainer.tsx","../../src/components/FilteredEntityLayout/EntityListContainer.tsx","../../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { stringifyEntityRef } from '@backstage/catalog-model';\nimport { StorageApi } from '@backstage/core-plugin-api';\nimport { isArray, isString } from 'lodash';\n\n/**\n * Migrate the starred entities from the old format (entity:<kind>:<namespace>:<name>) from the\n * old storage location (/settings/starredEntities) to entity references in the new location\n * (/starredEntities/entityRefs).\n *\n * This will only be executed once since the old location is cleared.\n *\n * @param storageApi - the StorageApi to migrate\n */\nexport async function performMigrationToTheNewBucket({\n storageApi,\n}: {\n storageApi: StorageApi;\n}) {\n const source = storageApi.forBucket('settings');\n const target = storageApi.forBucket('starredEntities');\n\n const oldStarredEntities = source.snapshot('starredEntities').value;\n\n if (!isArray(oldStarredEntities)) {\n // nothing to do\n return;\n }\n const targetEntities = new Set(\n target.snapshot<string[]>('entityRefs').value ?? [],\n );\n\n oldStarredEntities\n .filter(isString)\n // extract the old format 'entity:<kind>:<namespace>:<name>'\n .map(old => old.split(':'))\n // check if the format is valid\n .filter(split => split.length === 4 && split[0] === 'entity')\n // convert to entity references\n .map(([_, kind, namespace, name]) =>\n stringifyEntityRef({ kind, namespace, name }),\n )\n .forEach(e => targetEntities.add(e));\n\n await target.set('entityRefs', Array.from(targetEntities));\n\n await source.remove('starredEntities');\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 { StorageApi } from '@backstage/core-plugin-api';\nimport { StarredEntitiesApi } from '@backstage/plugin-catalog-react';\nimport { Observable } from '@backstage/types';\nimport ObservableImpl from 'zen-observable';\nimport { performMigrationToTheNewBucket } from './migration';\n\n/**\n * Default implementation of the StarredEntitiesApi that is backed by the StorageApi.\n *\n * @public\n */\nexport class DefaultStarredEntitiesApi implements StarredEntitiesApi {\n private readonly settingsStore: StorageApi;\n private starredEntities: Set<string>;\n\n constructor(opts: { storageApi: StorageApi }) {\n // no need to await. The updated content will be caught by the observe$\n performMigrationToTheNewBucket(opts).then();\n\n this.settingsStore = opts.storageApi.forBucket('starredEntities');\n\n this.starredEntities = new Set(\n this.settingsStore.snapshot<string[]>('entityRefs').value ?? [],\n );\n\n this.settingsStore.observe$<string[]>('entityRefs').subscribe({\n next: next => {\n this.starredEntities = new Set(next.value ?? []);\n this.notifyChanges();\n },\n });\n }\n\n async toggleStarred(entityRef: string): Promise<void> {\n if (this.starredEntities.has(entityRef)) {\n this.starredEntities.delete(entityRef);\n } else {\n this.starredEntities.add(entityRef);\n }\n\n await this.settingsStore.set(\n 'entityRefs',\n Array.from(this.starredEntities),\n );\n }\n\n starredEntitie$(): Observable<Set<string>> {\n return this.observable;\n }\n\n private readonly subscribers = new Set<\n ZenObservable.SubscriptionObserver<Set<string>>\n >();\n\n private readonly observable = new ObservableImpl<Set<string>>(subscriber => {\n // forward the the latest value\n subscriber.next(new Set(this.starredEntities));\n\n this.subscribers.add(subscriber);\n return () => {\n this.subscribers.delete(subscriber);\n };\n });\n\n private notifyChanges() {\n for (const subscription of this.subscribers) {\n subscription.next(new Set(this.starredEntities));\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 createExternalRouteRef,\n createRouteRef,\n} 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\nexport const rootRouteRef = createRouteRef({\n id: 'catalog',\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\n/**\n * Props for {@link AboutField}.\n *\n * @public\n */\nexport interface AboutFieldProps {\n label: string;\n value?: string;\n gridSizes?: Record<string, number>;\n children?: React.ReactNode;\n}\n\n/** @public */\nexport function AboutField(props: AboutFieldProps) {\n const { 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\n/**\n * Props for {@link AboutContent}.\n *\n * @public\n */\nexport interface AboutContentProps {\n entity: Entity;\n}\n\n/** @public */\nexport function AboutContent(props: AboutContentProps) {\n const { 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 ANNOTATION_EDIT_URL,\n ANNOTATION_LOCATION,\n DEFAULT_NAMESPACE,\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 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\n/**\n * Props for {@link AboutCard}.\n *\n * @public\n */\nexport interface AboutCardProps {\n variant?: InfoCardVariants;\n}\n\n/**\n * @public\n * @deprecated Please use EntityAboutCard instead\n */\nexport function AboutCard(props: AboutCardProps) {\n const { variant } = props;\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 =\n entity.metadata.annotations?.[ANNOTATION_EDIT_URL];\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 || 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?.[ANNOTATION_LOCATION];\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 catalogApiRef,\n EntityKindFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n root: {\n ...theme.typography.h4,\n },\n }),\n);\n\n/**\n * Props for {@link CatalogKindHeader}.\n *\n * @public\n */\nexport interface CatalogKindHeaderProps {\n initialFilter?: string;\n}\n\n/** @public */\nexport function CatalogKindHeader(props: CatalogKindHeaderProps) {\n const { initialFilter = 'component' } = props;\n const classes = useStyles();\n const catalogApi = useApi(catalogApiRef);\n const { value: allKinds } = useAsync(async () => {\n return await catalogApi\n .getEntityFacets({ facets: ['kind'] })\n .then(response => response.facets.kind?.map(f => f.value).sort() || []);\n });\n const { updateFilters, queryParameters } = useEntityList();\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';\nimport { IndexableDocument } from '@backstage/search-common';\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\n/**\n * Props for {@link CatalogSearchResultListItem}.\n *\n * @public\n */\nexport interface CatalogSearchResultListItemProps {\n result: IndexableDocument;\n}\n\n/** @public */\nexport function CatalogSearchResultListItem(\n props: CatalogSearchResultListItemProps,\n) {\n const result = props.result as any;\n\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/**\n * @public\n * @deprecated use {@link CatalogSearchResultListItemProps} instead\n */\nexport type CatalogResultListItemProps = CatalogSearchResultListItemProps;\n\n/**\n * @public\n * @deprecated use {@link CatalogSearchResultListItem} instead\n */\nexport const CatalogResultListItem = CatalogSearchResultListItem;\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 humanizeEntityRef,\n EntityRefLink,\n EntityRefLinks,\n} from '@backstage/plugin-catalog-react';\nimport { Chip } from '@material-ui/core';\nimport { CatalogTableRow } from './types';\nimport { OverflowTooltip, TableColumn } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\n\n// The columnFactories symbol is not directly exported, but through the\n// CatalogTable.columns field.\n/** @public */\nexport const columnFactories = Object.freeze({\n createNameColumn(options?: {\n defaultKind?: string;\n }): TableColumn<CatalogTableRow> {\n function formatContent(entity: Entity): string {\n return (\n entity.metadata?.title ||\n humanizeEntityRef(entity, {\n defaultKind: options?.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={options?.defaultKind || 'Component'}\n title={entity.metadata?.title}\n />\n ),\n };\n },\n createSystemColumn(): TableColumn<CatalogTableRow> {\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 createOwnerColumn(): TableColumn<CatalogTableRow> {\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 createSpecTypeColumn(): TableColumn<CatalogTableRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n hidden: true,\n };\n },\n createSpecLifecycleColumn(): TableColumn<CatalogTableRow> {\n return {\n title: 'Lifecycle',\n field: 'entity.spec.lifecycle',\n };\n },\n createMetadataDescriptionColumn(): TableColumn<CatalogTableRow> {\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 createTagsColumn(): TableColumn<CatalogTableRow> {\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","/*\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 ANNOTATION_EDIT_URL,\n ANNOTATION_VIEW_URL,\n RELATION_OWNED_BY,\n RELATION_PART_OF,\n} from '@backstage/catalog-model';\nimport {\n humanizeEntityRef,\n getEntityRelations,\n useEntityList,\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 { columnFactories } from './columns';\nimport { CatalogTableRow } from './types';\nimport {\n CodeSnippet,\n Table,\n TableColumn,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\nimport StarBorder from '@material-ui/icons/StarBorder';\nimport { withStyles } from '@material-ui/core/styles';\nimport Star from '@material-ui/icons/Star';\n\n/**\n * Props for {@link CatalogTable}.\n *\n * @public\n */\nexport interface CatalogTableProps {\n columns?: TableColumn<CatalogTableRow>[];\n actions?: TableProps<CatalogTableRow>['actions'];\n}\n\nconst YellowStar = withStyles({\n root: {\n color: '#f3ba37',\n },\n})(Star);\n\n/** @public */\nexport const CatalogTable = (props: CatalogTableProps) => {\n const { columns, actions } = props;\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const { loading, error, entities, filters } = useEntityList();\n\n const defaultColumns: TableColumn<CatalogTableRow>[] = 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<CatalogTableRow>['actions'] = [\n ({ entity }) => {\n const url = entity.metadata.annotations?.[ANNOTATION_VIEW_URL];\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 = entity.metadata.annotations?.[ANNOTATION_EDIT_URL];\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: () => (isStarred ? <YellowStar /> : <StarBorder />),\n tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites',\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: humanizeEntityRef(entity, {\n defaultKind: 'Component',\n }),\n ownedByRelationsTitle: ownedByRelations\n .map(r => humanizeEntityRef(r, { defaultKind: 'group' }))\n .join(', '),\n ownedByRelations,\n partOfSystemRelationTitle: partOfSystemRelations\n .map(r =>\n humanizeEntityRef(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<CatalogTableRow>\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\ninterface ExtraContextMenuItem {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n}\n\n// unstable context menu option, eg: disable the unregister entity menu\ninterface contextMenuOptions {\n disableUnregister: boolean;\n}\n\ninterface EntityContextMenuProps {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n onUnregisterEntity: () => void;\n onInspectEntity: () => void;\n}\n\nexport function EntityContextMenu(props: EntityContextMenuProps) {\n const {\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 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 EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n InspectEntityDialog,\n UnregisterEntityDialog,\n useAsyncEntity,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box, TabProps } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect, useState } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\n\n/** @public */\nexport type EntityLayoutRouteProps = {\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: EntityLayoutRouteProps) => null = () => null;\nattachComponentData(Route, dataKey, true);\nattachComponentData(Route, 'core.gatherMountPoints', true); // This causes all mount points that are discovered within this route to use the path of the route itself\n\nfunction EntityLayoutTitle(props: {\n title: string;\n entity: Entity | undefined;\n}) {\n const { entity, title } = props;\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\nfunction 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 !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\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\nfunction EntityLabels(props: { entity: Entity }) {\n const { entity } = props;\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\ninterface ExtraContextMenuItem {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n}\n\n// unstable context menu option, eg: disable the unregister entity menu\ninterface contextMenuOptions {\n disableUnregister: boolean;\n}\n\n/** @public */\nexport interface 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 *\n * @public\n */\nexport const EntityLayout = (props: EntityLayoutProps) => {\n const {\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n children,\n } = props;\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useAsyncEntity();\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<EntityLayoutRouteProps>() // all nodes, element data, maintain structure or not?\n .flatMap(({ props: elementProps }) => {\n if (!entity) {\n return [];\n } else if (elementProps.if && !elementProps.if(entity)) {\n return [];\n }\n\n return [\n {\n path: elementProps.path,\n title: elementProps.title,\n children: elementProps.children,\n tabProps: elementProps.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\ninterface DeleteEntityDialogProps {\n open: boolean;\n onClose: () => any;\n onConfirm: () => any;\n entity: Entity;\n}\n\nexport function DeleteEntityDialog(props: DeleteEntityDialogProps) {\n const { open, onClose, onConfirm, entity } = 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 { 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';\nimport { rootRouteRef } from '../../routes';\n\n/**\n * Returns true if the given entity has the orphan annotation given by the\n * catalog.\n *\n * @public\n */\nexport function isOrphan(entity: Entity): boolean {\n return entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true';\n}\n\n/**\n * Displays a warning alert if the entity is marked as orphan with the ability\n * to delete said entity.\n *\n * @public\n */\nexport function EntityOrphanWarning() {\n const navigate = useNavigate();\n const catalogLink = useRouteRef(rootRouteRef);\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} 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\ninterface 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\n/**\n * Returns true if the given entity has any processing errors on it.\n *\n * @public\n */\nexport async function hasCatalogProcessingErrors(\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 *\n * @public\n */\nexport function 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 {stringifyEntityRef(entity) !==\n stringifyEntityRef(ancestorError.entity) && (\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 */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { useAsyncEntity } from '@backstage/plugin-catalog-react';\nimport React, { ReactNode, ReactElement } 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\n/** @public */\nexport interface EntitySwitchCaseProps {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: ReactNode;\n}\n\nconst EntitySwitchCaseComponent = (_props: EntitySwitchCaseProps) => null;\n\nattachComponentData(EntitySwitchCaseComponent, ENTITY_SWITCH_KEY, true);\n\ninterface EntitySwitchCase {\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\n/**\n * Props for the {@link EntitySwitch} component.\n * @public\n */\nexport interface EntitySwitchProps {\n children: ReactNode;\n}\n\n/** @public */\nexport const EntitySwitch = (props: EntitySwitchProps) => {\n const { entity } = useAsyncEntity();\n const apis = useApiHolder();\n const results = useElementFilter(\n props.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: ReactElement) => {\n if (!entity) {\n return [];\n }\n const { if: condition, children: elementsChildren } =\n element.props as EntitySwitchCase;\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 = EntitySwitchCaseComponent;\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\n/**\n * For use in EntitySwitch.Case. Matches if the entity is of a given kind.\n * @public\n */\nexport function isKind(kind: string) {\n return (entity: Entity) => strCmp(entity.kind, kind);\n}\n\n/**\n * For use in EntitySwitch.Case. Matches if the entity is a Component of a given spec.type.\n * @public\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\n/**\n * For use in EntitySwitch.Case. Matches if the entity is in a given namespace.\n * @public\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 from 'react';\n\n/** @public */\nexport function FilteredEntityLayout(props: { children: React.ReactNode }) {\n return (\n <Grid container style={{ position: 'relative' }}>\n {props.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 { 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 } from 'react';\n\n/** @public */\nexport function FilterContainer(props: { children: React.ReactNode }) {\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 {props.children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {props.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 from 'react';\n\n/** @public */\nexport function EntityListContainer(props: { children: React.ReactNode }) {\n return (\n <Grid item xs={12} lg={10}>\n {props.children}\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 { CatalogClient } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\nimport {\n catalogApiRef,\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';\nimport { DefaultStarredEntitiesApi } from './apis';\nimport { AboutCardProps } from './components/AboutCard';\nimport { DefaultCatalogPageProps } from './components/CatalogPage';\nimport { DependencyOfComponentsCardProps } from './components/DependencyOfComponentsCard';\nimport { DependsOnComponentsCardProps } from './components/DependsOnComponentsCard';\nimport { DependsOnResourcesCardProps } from './components/DependsOnResourcesCard';\nimport { HasComponentsCardProps } from './components/HasComponentsCard';\nimport { HasResourcesCardProps } from './components/HasResourcesCard';\nimport { HasSubcomponentsCardProps } from './components/HasSubcomponentsCard';\nimport { HasSystemsCardProps } from './components/HasSystemsCard';\nimport { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard';\nimport { rootRouteRef } from './routes';\n\n/** @public */\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: rootRouteRef,\n catalogEntity: entityRouteRef,\n },\n externalRoutes: {\n createComponent: createComponentRouteRef,\n viewTechDoc: viewTechDocRouteRef,\n },\n});\n\n/** @public */\nexport const CatalogIndexPage: (props: DefaultCatalogPageProps) => JSX.Element =\n catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogIndexPage',\n component: () =>\n import('./components/CatalogPage').then(m => m.CatalogPage),\n mountPoint: rootRouteRef,\n }),\n );\n\n/** @public */\nexport const CatalogEntityPage: () => JSX.Element = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogEntityPage',\n component: () =>\n import('./components/CatalogEntityPage').then(m => m.CatalogEntityPage),\n mountPoint: entityRouteRef,\n }),\n);\n\n/** @public */\nexport const EntityAboutCard: (props: AboutCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityAboutCard',\n component: {\n lazy: () => import('./components/AboutCard').then(m => m.AboutCard),\n },\n }),\n );\n\n/** @public */\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\n/** @public */\nexport const EntityHasSystemsCard: (props: HasSystemsCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSystemsCard',\n component: {\n lazy: () =>\n import('./components/HasSystemsCard').then(m => m.HasSystemsCard),\n },\n }),\n );\n\n/** @public */\nexport const EntityHasComponentsCard: (\n props: HasComponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasComponentsCard',\n component: {\n lazy: () =>\n import('./components/HasComponentsCard').then(m => m.HasComponentsCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasSubcomponentsCard: (\n props: HasSubcomponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityHasResourcesCard: (\n props: HasResourcesCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasResourcesCard',\n component: {\n lazy: () =>\n import('./components/HasResourcesCard').then(m => m.HasResourcesCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityDependsOnComponentsCard: (\n props: DependsOnComponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityDependencyOfComponentsCard: (\n props: DependencyOfComponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityDependsOnResourcesCard: (\n props: DependsOnResourcesCardProps,\n) => JSX.Element = 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/** @public */\nexport const RelatedEntitiesCard: <T extends Entity>(\n props: RelatedEntitiesCardProps<T>,\n) => JSX.Element = 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","capitalize","Edit","makeStyles"],"mappings":"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"}
@@ -1,5 +1,7 @@
1
- export { A as AboutCard, d as AboutContent, e as AboutField } from './index-6ca877bd.esm.js';
1
+ export { A as AboutCard, d as AboutContent, e as AboutField } from './index-1f9336e4.esm.js';
2
+ import 'zen-observable';
2
3
  import '@backstage/catalog-model';
4
+ import 'lodash';
3
5
  import '@backstage/core-components';
4
6
  import '@backstage/core-plugin-api';
5
7
  import '@backstage/integration-react';
@@ -11,10 +13,11 @@ import '@material-ui/icons/Edit';
11
13
  import 'react';
12
14
  import 'react-use/lib/useAsync';
13
15
  import '@material-ui/icons/OpenInNew';
14
- import 'lodash';
16
+ import '@material-ui/icons/StarBorder';
17
+ import '@material-ui/core/styles';
18
+ import '@material-ui/icons/Star';
15
19
  import '@material-ui/lab';
16
20
  import 'react-router';
17
- import '@material-ui/core/styles';
18
21
  import '@material-ui/icons/Cancel';
19
22
  import '@material-ui/icons/BugReport';
20
23
  import '@material-ui/icons/MoreVert';
@@ -22,4 +25,4 @@ import '@backstage/plugin-catalog-common';
22
25
  import '@backstage/errors';
23
26
  import '@backstage/catalog-client';
24
27
  import '@material-ui/icons/FilterList';
25
- //# sourceMappingURL=index-31a771c4.esm.js.map
28
+ //# sourceMappingURL=index-3cf25427.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-3cf25427.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -3,8 +3,10 @@ import { useOutlet } from 'react-router';
3
3
  import { PageWithHeader, Content, ContentHeader, CreateButton, SupportButton } from '@backstage/core-components';
4
4
  import { useApi, configApiRef, useRouteRef } from '@backstage/core-plugin-api';
5
5
  import { EntityListProvider, EntityTypePicker, UserListPicker, EntityOwnerPicker, EntityLifecyclePicker, EntityTagPicker } from '@backstage/plugin-catalog-react';
6
- import { c as createComponentRouteRef, C as CatalogKindHeader, F as FilteredEntityLayout, a as FilterContainer, E as EntityListContainer, b as CatalogTable } from './index-6ca877bd.esm.js';
6
+ import { c as createComponentRouteRef, C as CatalogKindHeader, F as FilteredEntityLayout, a as FilterContainer, E as EntityListContainer, b as CatalogTable } from './index-1f9336e4.esm.js';
7
+ import 'zen-observable';
7
8
  import '@backstage/catalog-model';
9
+ import 'lodash';
8
10
  import '@backstage/integration-react';
9
11
  import '@material-ui/core';
10
12
  import '@material-ui/icons/Cached';
@@ -12,9 +14,10 @@ import '@material-ui/icons/Description';
12
14
  import '@material-ui/icons/Edit';
13
15
  import 'react-use/lib/useAsync';
14
16
  import '@material-ui/icons/OpenInNew';
15
- import 'lodash';
16
- import '@material-ui/lab';
17
+ import '@material-ui/icons/StarBorder';
17
18
  import '@material-ui/core/styles';
19
+ import '@material-ui/icons/Star';
20
+ import '@material-ui/lab';
18
21
  import '@material-ui/icons/Cancel';
19
22
  import '@material-ui/icons/BugReport';
20
23
  import '@material-ui/icons/MoreVert';
@@ -52,4 +55,4 @@ function CatalogPage(props) {
52
55
  }
53
56
 
54
57
  export { CatalogPage, DefaultCatalogPage };
55
- //# sourceMappingURL=index-0518ad02.esm.js.map
58
+ //# sourceMappingURL=index-61fe5994.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index-0518ad02.esm.js","sources":["../../src/components/CatalogPage/DefaultCatalogPage.tsx","../../src/components/CatalogPage/CatalogPage.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n 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, CatalogTableRow } from '../CatalogTable';\nimport {\n FilteredEntityLayout,\n EntityListContainer,\n FilterContainer,\n} from '../FilteredEntityLayout';\nimport { CatalogKindHeader } from '../CatalogKindHeader';\n\n/**\n * Props for root catalog pages.\n *\n * @public\n */\nexport interface DefaultCatalogPageProps {\n initiallySelectedFilter?: UserListFilterKind;\n columns?: TableColumn<CatalogTableRow>[];\n actions?: TableProps<CatalogTableRow>['actions'];\n}\n\nexport function DefaultCatalogPage(props: DefaultCatalogPageProps) {\n const { columns, actions, initiallySelectedFilter = 'owned' } = props;\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 function CatalogPage(props: DefaultCatalogPageProps) {\n const outlet = useOutlet();\n\n return outlet || <DefaultCatalogPage {...props} />;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;4BAwDmC,OAAgC;AAxDnE;AAyDE,QAAM,EAAE,SAAS,SAAS,0BAA0B,YAAY;AAChE,QAAM,UACJ,aAAO,cAAc,kBAAkB,yBAAvC,YAA+D;AACjE,QAAM,sBAAsB,YAAY;AAExC,6CACG,gBAAD;AAAA,IAAgB,OAAO,GAAG;AAAA,IAAmB,SAAQ;AAAA,yCAClD,oBAAD,0CACG,SAAD,0CACG,eAAD;AAAA,IAAe,oDAAiB,mBAAD;AAAA,yCAC5B,cAAD;AAAA,IACE,OAAM;AAAA,IACN,IAAI,uBAAuB;AAAA,0CAE5B,eAAD,MAAe,4EAEhB,sBAAD,0CACG,iBAAD,0CACG,kBAAD,2CACC,gBAAD;AAAA,IAAgB,eAAe;AAAA,0CAC9B,mBAAD,2CACC,uBAAD,2CACC,iBAAD,4CAED,qBAAD,0CACG,cAAD;AAAA,IAAc;AAAA,IAAkB;AAAA;AAAA;;qBC3DlB,OAAgC;AAC1D,QAAM,SAAS;AAEf,SAAO,8CAAW,oBAAD;AAAA,OAAwB;AAAA;AAAA;;;;"}
1
+ {"version":3,"file":"index-61fe5994.esm.js","sources":["../../src/components/CatalogPage/DefaultCatalogPage.tsx","../../src/components/CatalogPage/CatalogPage.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n 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, CatalogTableRow } from '../CatalogTable';\nimport {\n FilteredEntityLayout,\n EntityListContainer,\n FilterContainer,\n} from '../FilteredEntityLayout';\nimport { CatalogKindHeader } from '../CatalogKindHeader';\n\n/**\n * Props for root catalog pages.\n *\n * @public\n */\nexport interface DefaultCatalogPageProps {\n initiallySelectedFilter?: UserListFilterKind;\n columns?: TableColumn<CatalogTableRow>[];\n actions?: TableProps<CatalogTableRow>['actions'];\n}\n\nexport function DefaultCatalogPage(props: DefaultCatalogPageProps) {\n const { columns, actions, initiallySelectedFilter = 'owned' } = props;\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 function CatalogPage(props: DefaultCatalogPageProps) {\n const outlet = useOutlet();\n\n return outlet || <DefaultCatalogPage {...props} />;\n}\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;4BAwDmC,OAAgC;AAxDnE;AAyDE,QAAM,EAAE,SAAS,SAAS,0BAA0B,YAAY;AAChE,QAAM,UACJ,aAAO,cAAc,kBAAkB,yBAAvC,YAA+D;AACjE,QAAM,sBAAsB,YAAY;AAExC,6CACG,gBAAD;AAAA,IAAgB,OAAO,GAAG;AAAA,IAAmB,SAAQ;AAAA,yCAClD,oBAAD,0CACG,SAAD,0CACG,eAAD;AAAA,IAAe,oDAAiB,mBAAD;AAAA,yCAC5B,cAAD;AAAA,IACE,OAAM;AAAA,IACN,IAAI,uBAAuB;AAAA,0CAE5B,eAAD,MAAe,4EAEhB,sBAAD,0CACG,iBAAD,0CACG,kBAAD,2CACC,gBAAD;AAAA,IAAgB,eAAe;AAAA,0CAC9B,mBAAD,2CACC,uBAAD,2CACC,iBAAD,4CAED,qBAAD,0CACG,cAAD;AAAA,IAAc;AAAA,IAAkB;AAAA;AAAA;;qBC3DlB,OAAgC;AAC1D,QAAM,SAAS;AAEf,SAAO,8CAAW,oBAAD;AAAA,OAAwB;AAAA;AAAA;;;;"}
@@ -14,7 +14,7 @@ const useEntityFromUrl = () => {
14
14
  error,
15
15
  loading,
16
16
  retry: refresh
17
- } = useAsyncRetry(() => catalogApi.getEntityByName({ kind, namespace, name }), [catalogApi, kind, namespace, name]);
17
+ } = useAsyncRetry(() => catalogApi.getEntityByRef({ kind, namespace, name }), [catalogApi, kind, namespace, name]);
18
18
  useEffect(() => {
19
19
  if (!name) {
20
20
  errorApi.post(new Error("No name provided!"));
@@ -31,4 +31,4 @@ function CatalogEntityPage() {
31
31
  }
32
32
 
33
33
  export { CatalogEntityPage };
34
- //# sourceMappingURL=index-7f3caf38.esm.js.map
34
+ //# sourceMappingURL=index-7e69bc27.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index-7e69bc27.esm.js","sources":["../../src/components/CatalogEntityPage/useEntityFromUrl.ts","../../src/components/CatalogEntityPage/CatalogEntityPage.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n errorApiRef,\n useApi,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n EntityLoadingStatus,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport { useEffect } from 'react';\nimport { useNavigate } from 'react-router';\nimport useAsyncRetry from 'react-use/lib/useAsyncRetry';\n\nexport const useEntityFromUrl = (): EntityLoadingStatus => {\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const navigate = useNavigate();\n const errorApi = useApi(errorApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n const {\n value: entity,\n error,\n loading,\n retry: refresh,\n } = useAsyncRetry(\n () => catalogApi.getEntityByRef({ kind, namespace, name }),\n [catalogApi, kind, namespace, name],\n );\n\n useEffect(() => {\n if (!name) {\n errorApi.post(new Error('No name provided!'));\n navigate('/');\n }\n }, [errorApi, navigate, error, loading, entity, name]);\n\n return { entity, loading, error, refresh };\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 { Outlet } from 'react-router';\nimport { AsyncEntityProvider } from '@backstage/plugin-catalog-react';\nimport { useEntityFromUrl } from './useEntityFromUrl';\n\n/** @public */\nexport function CatalogEntityPage() {\n return (\n <AsyncEntityProvider {...useEntityFromUrl()}>\n <Outlet />\n </AsyncEntityProvider>\n );\n}\n"],"names":[],"mappings":";;;;;;MA8Ba,mBAAmB,MAA2B;AACzD,QAAM,EAAE,MAAM,WAAW,SAAS,kBAAkB;AACpD,QAAM,WAAW;AACjB,QAAM,WAAW,OAAO;AACxB,QAAM,aAAa,OAAO;AAE1B,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cACF,MAAM,WAAW,eAAe,EAAE,MAAM,WAAW,SACnD,CAAC,YAAY,MAAM,WAAW;AAGhC,YAAU,MAAM;AACd,QAAI,CAAC,MAAM;AACT,eAAS,KAAK,IAAI,MAAM;AACxB,eAAS;AAAA;AAAA,KAEV,CAAC,UAAU,UAAU,OAAO,SAAS,QAAQ;AAEhD,SAAO,EAAE,QAAQ,SAAS,OAAO;AAAA;;6BC/BC;AAClC,6CACG,qBAAD;AAAA,OAAyB;AAAA,yCACtB,QAAD;AAAA;;;;"}
package/dist/index.d.ts CHANGED
@@ -1,14 +1,33 @@
1
1
  /// <reference types="react" />
2
+ import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
3
+ import { StorageApi, IconComponent, ApiHolder } from '@backstage/core-plugin-api';
4
+ import { StarredEntitiesApi, UserListFilterKind } from '@backstage/plugin-catalog-react';
5
+ import { Observable } from '@backstage/types';
2
6
  import { InfoCardVariants, TableColumn, TableProps } from '@backstage/core-components';
3
- import { Entity, EntityName } from '@backstage/catalog-model';
7
+ import { Entity, CompoundEntityRef } from '@backstage/catalog-model';
4
8
  import React, { ReactNode } from 'react';
5
9
  import { IndexableDocument } from '@backstage/search-common';
6
- import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
7
- import { IconComponent, ApiHolder } from '@backstage/core-plugin-api';
8
10
  import { TabProps } from '@material-ui/core';
9
11
  import { Overrides } from '@material-ui/core/styles/overrides';
10
12
  import { StyleRules } from '@material-ui/core/styles/withStyles';
11
- import { UserListFilterKind } from '@backstage/plugin-catalog-react';
13
+
14
+ /**
15
+ * Default implementation of the StarredEntitiesApi that is backed by the StorageApi.
16
+ *
17
+ * @public
18
+ */
19
+ declare class DefaultStarredEntitiesApi implements StarredEntitiesApi {
20
+ private readonly settingsStore;
21
+ private starredEntities;
22
+ constructor(opts: {
23
+ storageApi: StorageApi;
24
+ });
25
+ toggleStarred(entityRef: string): Promise<void>;
26
+ starredEntitie$(): Observable<Set<string>>;
27
+ private readonly subscribers;
28
+ private readonly observable;
29
+ private notifyChanges;
30
+ }
12
31
 
13
32
  /**
14
33
  * Props for {@link AboutCard}.
@@ -87,9 +106,9 @@ interface CatalogTableRow {
87
106
  resolved: {
88
107
  name: string;
89
108
  partOfSystemRelationTitle?: string;
90
- partOfSystemRelations: EntityName[];
109
+ partOfSystemRelations: CompoundEntityRef[];
91
110
  ownedByRelationsTitle?: string;
92
- ownedByRelations: EntityName[];
111
+ ownedByRelations: CompoundEntityRef[];
93
112
  };
94
113
  }
95
114
 
@@ -372,4 +391,4 @@ declare const EntityDependsOnResourcesCard: (props: DependsOnResourcesCardProps)
372
391
  /** @public */
373
392
  declare const RelatedEntitiesCard: <T extends Entity>(props: RelatedEntitiesCardProps<T>) => JSX.Element;
374
393
 
375
- export { AboutCard, AboutCardProps, AboutContent, AboutContentProps, AboutField, AboutFieldProps, BackstageOverrides, CatalogEntityPage, CatalogIndexPage, CatalogKindHeader, CatalogKindHeaderProps, CatalogResultListItem, CatalogResultListItemProps, CatalogSearchResultListItem, CatalogSearchResultListItemProps, CatalogTable, CatalogTableProps, CatalogTableRow, DefaultCatalogPageProps, DependencyOfComponentsCardProps, DependsOnComponentsCardProps, DependsOnResourcesCardProps, EntityAboutCard, EntityDependencyOfComponentsCard, EntityDependsOnComponentsCard, EntityDependsOnResourcesCard, EntityHasComponentsCard, EntityHasResourcesCard, EntityHasSubcomponentsCard, EntityHasSystemsCard, EntityLayout, EntityLayoutProps, EntityLayoutRouteProps, EntityLinksCard, EntityLinksCardProps, EntityLinksEmptyStateClassKey, EntityListContainer, EntityOrphanWarning, EntityProcessingErrorsPanel, EntitySwitch, EntitySwitchCaseProps, EntitySwitchProps, FilterContainer, FilteredEntityLayout, HasComponentsCardProps, HasResourcesCardProps, HasSubcomponentsCardProps, HasSystemsCardProps, PluginCatalogComponentsNameToClassKey, RelatedEntitiesCard, RelatedEntitiesCardProps, SystemDiagramCardClassKey, catalogPlugin, hasCatalogProcessingErrors, isComponentType, isKind, isNamespace, isOrphan };
394
+ export { AboutCard, AboutCardProps, AboutContent, AboutContentProps, AboutField, AboutFieldProps, BackstageOverrides, CatalogEntityPage, CatalogIndexPage, CatalogKindHeader, CatalogKindHeaderProps, CatalogResultListItem, CatalogResultListItemProps, CatalogSearchResultListItem, CatalogSearchResultListItemProps, CatalogTable, CatalogTableProps, CatalogTableRow, DefaultCatalogPageProps, DefaultStarredEntitiesApi, DependencyOfComponentsCardProps, DependsOnComponentsCardProps, DependsOnResourcesCardProps, EntityAboutCard, EntityDependencyOfComponentsCard, EntityDependsOnComponentsCard, EntityDependsOnResourcesCard, EntityHasComponentsCard, EntityHasResourcesCard, EntityHasSubcomponentsCard, EntityHasSystemsCard, EntityLayout, EntityLayoutProps, EntityLayoutRouteProps, EntityLinksCard, EntityLinksCardProps, EntityLinksEmptyStateClassKey, EntityListContainer, EntityOrphanWarning, EntityProcessingErrorsPanel, EntitySwitch, EntitySwitchCaseProps, EntitySwitchProps, FilterContainer, FilteredEntityLayout, HasComponentsCardProps, HasResourcesCardProps, HasSubcomponentsCardProps, HasSystemsCardProps, PluginCatalogComponentsNameToClassKey, RelatedEntitiesCard, RelatedEntitiesCardProps, SystemDiagramCardClassKey, catalogPlugin, hasCatalogProcessingErrors, isComponentType, isKind, isNamespace, isOrphan };
package/dist/index.esm.js CHANGED
@@ -1,5 +1,7 @@
1
- export { A as AboutCard, d as AboutContent, e as AboutField, f as CatalogEntityPage, g as CatalogIndexPage, C as CatalogKindHeader, s as CatalogResultListItem, r as CatalogSearchResultListItem, b as CatalogTable, i as EntityAboutCard, j as EntityDependencyOfComponentsCard, k as EntityDependsOnComponentsCard, l as EntityDependsOnResourcesCard, m as EntityHasComponentsCard, n as EntityHasResourcesCard, o as EntityHasSubcomponentsCard, p as EntityHasSystemsCard, t as EntityLayout, q as EntityLinksCard, E as EntityListContainer, u as EntityOrphanWarning, w as EntityProcessingErrorsPanel, y as EntitySwitch, a as FilterContainer, F as FilteredEntityLayout, R as RelatedEntitiesCard, h as catalogPlugin, x as hasCatalogProcessingErrors, D as isComponentType, z as isKind, B as isNamespace, v as isOrphan } from './esm/index-6ca877bd.esm.js';
1
+ export { A as AboutCard, d as AboutContent, e as AboutField, f as CatalogEntityPage, g as CatalogIndexPage, C as CatalogKindHeader, s as CatalogResultListItem, r as CatalogSearchResultListItem, b as CatalogTable, D as DefaultStarredEntitiesApi, i as EntityAboutCard, j as EntityDependencyOfComponentsCard, k as EntityDependsOnComponentsCard, l as EntityDependsOnResourcesCard, m as EntityHasComponentsCard, n as EntityHasResourcesCard, o as EntityHasSubcomponentsCard, p as EntityHasSystemsCard, t as EntityLayout, q as EntityLinksCard, E as EntityListContainer, u as EntityOrphanWarning, w as EntityProcessingErrorsPanel, y as EntitySwitch, a as FilterContainer, F as FilteredEntityLayout, R as RelatedEntitiesCard, h as catalogPlugin, x as hasCatalogProcessingErrors, G as isComponentType, z as isKind, B as isNamespace, v as isOrphan } from './esm/index-1f9336e4.esm.js';
2
+ import 'zen-observable';
2
3
  import '@backstage/catalog-model';
4
+ import 'lodash';
3
5
  import '@backstage/core-components';
4
6
  import '@backstage/core-plugin-api';
5
7
  import '@backstage/integration-react';
@@ -11,10 +13,11 @@ import '@material-ui/icons/Edit';
11
13
  import 'react';
12
14
  import 'react-use/lib/useAsync';
13
15
  import '@material-ui/icons/OpenInNew';
14
- import 'lodash';
16
+ import '@material-ui/icons/StarBorder';
17
+ import '@material-ui/core/styles';
18
+ import '@material-ui/icons/Star';
15
19
  import '@material-ui/lab';
16
20
  import 'react-router';
17
- import '@material-ui/core/styles';
18
21
  import '@material-ui/icons/Cancel';
19
22
  import '@material-ui/icons/BugReport';
20
23
  import '@material-ui/icons/MoreVert';
@@ -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.9.0",
4
+ "version": "0.9.1",
5
5
  "main": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "license": "Apache-2.0",
@@ -34,16 +34,17 @@
34
34
  "clean": "backstage-cli package clean"
35
35
  },
36
36
  "dependencies": {
37
- "@backstage/catalog-client": "^0.7.2",
38
- "@backstage/catalog-model": "^0.11.0",
39
- "@backstage/core-components": "^0.8.10",
40
- "@backstage/core-plugin-api": "^0.7.0",
37
+ "@backstage/catalog-client": "^0.8.0",
38
+ "@backstage/catalog-model": "^0.12.0",
39
+ "@backstage/core-components": "^0.9.0",
40
+ "@backstage/core-plugin-api": "^0.8.0",
41
41
  "@backstage/errors": "^0.2.2",
42
- "@backstage/integration-react": "^0.1.23",
43
- "@backstage/plugin-catalog-common": "^0.1.4",
44
- "@backstage/plugin-catalog-react": "^0.7.0",
45
- "@backstage/search-common": "^0.2.4",
42
+ "@backstage/integration-react": "^0.1.24",
43
+ "@backstage/plugin-catalog-common": "^0.2.0",
44
+ "@backstage/plugin-catalog-react": "^0.8.0",
45
+ "@backstage/search-common": "^0.3.0",
46
46
  "@backstage/theme": "^0.2.15",
47
+ "@backstage/types": "^0.1.2",
47
48
  "@material-ui/core": "^4.12.2",
48
49
  "@material-ui/icons": "^4.9.1",
49
50
  "@material-ui/lab": "4.0.0-alpha.57",
@@ -51,18 +52,19 @@
51
52
  "lodash": "^4.17.21",
52
53
  "react-helmet": "6.1.0",
53
54
  "react-router": "6.0.0-beta.0",
54
- "react-use": "^17.2.4"
55
+ "react-use": "^17.2.4",
56
+ "zen-observable": "^0.8.15"
55
57
  },
56
58
  "peerDependencies": {
57
59
  "@types/react": "^16.13.1 || ^17.0.0",
58
60
  "react": "^16.13.1 || ^17.0.0"
59
61
  },
60
62
  "devDependencies": {
61
- "@backstage/cli": "^0.14.1",
62
- "@backstage/core-app-api": "^0.5.4",
63
- "@backstage/dev-utils": "^0.2.23",
64
- "@backstage/plugin-permission-react": "^0.3.2",
65
- "@backstage/test-utils": "^0.2.6",
63
+ "@backstage/cli": "^0.15.0",
64
+ "@backstage/core-app-api": "^0.6.0",
65
+ "@backstage/dev-utils": "^0.2.24",
66
+ "@backstage/plugin-permission-react": "^0.3.3",
67
+ "@backstage/test-utils": "^0.3.0",
66
68
  "@testing-library/jest-dom": "^5.10.1",
67
69
  "@testing-library/react": "^11.2.5",
68
70
  "@testing-library/user-event": "^13.1.8",
@@ -72,5 +74,5 @@
72
74
  "files": [
73
75
  "dist"
74
76
  ],
75
- "gitHead": "a15da6ea1e3e8adc37be98be064071c8b5279b4a"
77
+ "gitHead": "04bb0dd824b78f6b57dac62c3015e681f094045c"
76
78
  }
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-31a771c4.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-6ca877bd.esm.js","sources":["../../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/CatalogSearchResultListItem/CatalogSearchResultListItem.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/EntitySwitch/EntitySwitch.tsx","../../src/components/EntitySwitch/conditions.ts","../../src/components/FilteredEntityLayout/FilteredEntityLayout.tsx","../../src/components/FilteredEntityLayout/FilterContainer.tsx","../../src/components/FilteredEntityLayout/EntityListContainer.tsx","../../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { 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\n/**\n * Props for {@link AboutField}.\n *\n * @public\n */\nexport interface AboutFieldProps {\n label: string;\n value?: string;\n gridSizes?: Record<string, number>;\n children?: React.ReactNode;\n}\n\n/** @public */\nexport function AboutField(props: AboutFieldProps) {\n const { 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\n/**\n * Props for {@link AboutContent}.\n *\n * @public\n */\nexport interface AboutContentProps {\n entity: Entity;\n}\n\n/** @public */\nexport function AboutContent(props: AboutContentProps) {\n const { 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 ANNOTATION_LOCATION,\n DEFAULT_NAMESPACE,\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\n/**\n * Props for {@link AboutCard}.\n *\n * @public\n */\nexport interface AboutCardProps {\n variant?: InfoCardVariants;\n}\n\n/**\n * @public\n * @deprecated Please use EntityAboutCard instead\n */\nexport function AboutCard(props: AboutCardProps) {\n const { variant } = props;\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 || 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?.[ANNOTATION_LOCATION];\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 catalogApiRef,\n EntityKindFilter,\n useEntityList,\n} from '@backstage/plugin-catalog-react';\nimport useAsync from 'react-use/lib/useAsync';\nimport { useApi } from '@backstage/core-plugin-api';\n\nconst useStyles = makeStyles((theme: Theme) =>\n createStyles({\n root: {\n ...theme.typography.h4,\n },\n }),\n);\n\n/**\n * Props for {@link CatalogKindHeader}.\n *\n * @public\n */\nexport interface CatalogKindHeaderProps {\n initialFilter?: string;\n}\n\n/** @public */\nexport function CatalogKindHeader(props: CatalogKindHeaderProps) {\n const { initialFilter = 'component' } = props;\n const classes = useStyles();\n const catalogApi = useApi(catalogApiRef);\n const { value: allKinds } = useAsync(async () => {\n return await catalogApi\n .getEntityFacets({ facets: ['kind'] })\n .then(response => response.facets.kind?.map(f => f.value).sort() || []);\n });\n const { updateFilters, queryParameters } = useEntityList();\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';\nimport { IndexableDocument } from '@backstage/search-common';\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\n/**\n * Props for {@link CatalogSearchResultListItem}.\n *\n * @public\n */\nexport interface CatalogSearchResultListItemProps {\n result: IndexableDocument;\n}\n\n/** @public */\nexport function CatalogSearchResultListItem(\n props: CatalogSearchResultListItemProps,\n) {\n const result = props.result as any;\n\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/**\n * @public\n * @deprecated use {@link CatalogSearchResultListItemProps} instead\n */\nexport type CatalogResultListItemProps = CatalogSearchResultListItemProps;\n\n/**\n * @public\n * @deprecated use {@link CatalogSearchResultListItem} instead\n */\nexport const CatalogResultListItem = CatalogSearchResultListItem;\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 { CatalogTableRow } from './types';\nimport { OverflowTooltip, TableColumn } from '@backstage/core-components';\nimport { Entity } from '@backstage/catalog-model';\n\n// The columnFactories symbol is not directly exported, but through the\n// CatalogTable.columns field.\n/** @public */\nexport const columnFactories = Object.freeze({\n createNameColumn(options?: {\n defaultKind?: string;\n }): TableColumn<CatalogTableRow> {\n function formatContent(entity: Entity): string {\n return (\n entity.metadata?.title ||\n formatEntityRefTitle(entity, {\n defaultKind: options?.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={options?.defaultKind || 'Component'}\n title={entity.metadata?.title}\n />\n ),\n };\n },\n createSystemColumn(): TableColumn<CatalogTableRow> {\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 createOwnerColumn(): TableColumn<CatalogTableRow> {\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 createSpecTypeColumn(): TableColumn<CatalogTableRow> {\n return {\n title: 'Type',\n field: 'entity.spec.type',\n hidden: true,\n };\n },\n createSpecLifecycleColumn(): TableColumn<CatalogTableRow> {\n return {\n title: 'Lifecycle',\n field: 'entity.spec.lifecycle',\n };\n },\n createMetadataDescriptionColumn(): TableColumn<CatalogTableRow> {\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 createTagsColumn(): TableColumn<CatalogTableRow> {\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","/*\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 useEntityList,\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 { columnFactories } from './columns';\nimport { CatalogTableRow } from './types';\nimport {\n CodeSnippet,\n Table,\n TableColumn,\n TableProps,\n WarningPanel,\n} from '@backstage/core-components';\n\n/**\n * Props for {@link CatalogTable}.\n *\n * @public\n */\nexport interface CatalogTableProps {\n columns?: TableColumn<CatalogTableRow>[];\n actions?: TableProps<CatalogTableRow>['actions'];\n}\n\n/** @public */\nexport const CatalogTable = (props: CatalogTableProps) => {\n const { columns, actions } = props;\n const { isStarredEntity, toggleStarredEntity } = useStarredEntities();\n const { loading, error, entities, filters } = useEntityList();\n\n const defaultColumns: TableColumn<CatalogTableRow>[] = 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<CatalogTableRow>['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<CatalogTableRow>\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\ninterface ExtraContextMenuItem {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n}\n\n// unstable context menu option, eg: disable the unregister entity menu\ninterface contextMenuOptions {\n disableUnregister: boolean;\n}\n\ninterface EntityContextMenuProps {\n UNSTABLE_extraContextMenuItems?: ExtraContextMenuItem[];\n UNSTABLE_contextMenuOptions?: contextMenuOptions;\n onUnregisterEntity: () => void;\n onInspectEntity: () => void;\n}\n\nexport function EntityContextMenu(props: EntityContextMenuProps) {\n const {\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 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 EntityRefLinks,\n FavoriteEntity,\n getEntityRelations,\n InspectEntityDialog,\n UnregisterEntityDialog,\n useEntity,\n useEntityCompoundName,\n} from '@backstage/plugin-catalog-react';\nimport { Box, TabProps } from '@material-ui/core';\nimport { Alert } from '@material-ui/lab';\nimport React, { useEffect, useState } from 'react';\nimport { useLocation, useNavigate } from 'react-router';\nimport { EntityContextMenu } from '../EntityContextMenu/EntityContextMenu';\n\n/** @public */\nexport type EntityLayoutRouteProps = {\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: EntityLayoutRouteProps) => null = () => null;\nattachComponentData(Route, dataKey, true);\nattachComponentData(Route, 'core.gatherMountPoints', true); // This causes all mount points that are discovered within this route to use the path of the route itself\n\nfunction EntityLayoutTitle(props: {\n title: string;\n entity: Entity | undefined;\n}) {\n const { entity, title } = props;\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\nfunction 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 !== DEFAULT_NAMESPACE ? ` in ${namespace}` : ''\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\nfunction EntityLabels(props: { entity: Entity }) {\n const { entity } = props;\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\ninterface ExtraContextMenuItem {\n title: string;\n Icon: IconComponent;\n onClick: () => void;\n}\n\n// unstable context menu option, eg: disable the unregister entity menu\ninterface contextMenuOptions {\n disableUnregister: boolean;\n}\n\n/** @public */\nexport interface 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 *\n * @public\n */\nexport const EntityLayout = (props: EntityLayoutProps) => {\n const {\n UNSTABLE_extraContextMenuItems,\n UNSTABLE_contextMenuOptions,\n children,\n } = props;\n const { kind, namespace, name } = useEntityCompoundName();\n const { entity, loading, error } = useEntity();\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<EntityLayoutRouteProps>() // all nodes, element data, maintain structure or not?\n .flatMap(({ props: elementProps }) => {\n if (elementProps.if && entity && !elementProps.if(entity)) {\n return [];\n }\n\n return [\n {\n path: elementProps.path,\n title: elementProps.title,\n children: elementProps.children,\n tabProps: elementProps.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\ninterface DeleteEntityDialogProps {\n open: boolean;\n onClose: () => any;\n onConfirm: () => any;\n entity: Entity;\n}\n\nexport function DeleteEntityDialog(props: DeleteEntityDialogProps) {\n const { open, onClose, onConfirm, entity } = 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\n/**\n * Returns true if the given entity has the orphan annotation given by the\n * catalog.\n *\n * @public\n */\nexport function isOrphan(entity: Entity): boolean {\n return entity?.metadata?.annotations?.['backstage.io/orphan'] === 'true';\n}\n\n/**\n * Displays a warning alert if the entity is marked as orphan with the ability\n * to delete said entity.\n *\n * @public\n */\nexport function 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} 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\ninterface 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\n/**\n * Returns true if the given entity has any processing errors on it.\n *\n * @public\n */\nexport async function hasCatalogProcessingErrors(\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 *\n * @public\n */\nexport function 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 {stringifyEntityRef(entity) !==\n stringifyEntityRef(ancestorError.entity) && (\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 */\n\nimport { Entity } from '@backstage/catalog-model';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport React, { ReactNode, ReactElement } 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\n/** @public */\nexport interface EntitySwitchCaseProps {\n if?: (\n entity: Entity,\n context: { apis: ApiHolder },\n ) => boolean | Promise<boolean>;\n children: ReactNode;\n}\n\nconst EntitySwitchCaseComponent = (_props: EntitySwitchCaseProps) => null;\n\nattachComponentData(EntitySwitchCaseComponent, ENTITY_SWITCH_KEY, true);\n\ninterface EntitySwitchCase {\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\n/**\n * Props for the {@link EntitySwitch} component.\n * @public\n */\nexport interface EntitySwitchProps {\n children: ReactNode;\n}\n\n/** @public */\nexport const EntitySwitch = (props: EntitySwitchProps) => {\n const { entity } = useEntity();\n const apis = useApiHolder();\n const results = useElementFilter(\n props.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: ReactElement) => {\n const { if: condition, children: elementsChildren } =\n element.props as EntitySwitchCase;\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 = EntitySwitchCaseComponent;\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\n/**\n * For use in EntitySwitch.Case. Matches if the entity is of a given kind.\n * @public\n */\nexport function isKind(kind: string) {\n return (entity: Entity) => strCmp(entity?.kind, kind);\n}\n\n/**\n * For use in EntitySwitch.Case. Matches if the entity is a Component of a given spec.type.\n * @public\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\n/**\n * For use in EntitySwitch.Case. Matches if the entity is in a given namespace.\n * @public\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 from 'react';\n\n/** @public */\nexport function FilteredEntityLayout(props: { children: React.ReactNode }) {\n return (\n <Grid container style={{ position: 'relative' }}>\n {props.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 { 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 } from 'react';\n\n/** @public */\nexport function FilterContainer(props: { children: React.ReactNode }) {\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 {props.children}\n </Box>\n </Drawer>\n </>\n ) : (\n <Grid item lg={2}>\n {props.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 from 'react';\n\n/** @public */\nexport function EntityListContainer(props: { children: React.ReactNode }) {\n return (\n <Grid item xs={12} lg={10}>\n {props.children}\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 { CatalogClient } from '@backstage/catalog-client';\nimport { Entity } from '@backstage/catalog-model';\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';\nimport { AboutCardProps } from './components/AboutCard';\nimport { DefaultCatalogPageProps } from './components/CatalogPage';\nimport { DependencyOfComponentsCardProps } from './components/DependencyOfComponentsCard';\nimport { DependsOnComponentsCardProps } from './components/DependsOnComponentsCard';\nimport { DependsOnResourcesCardProps } from './components/DependsOnResourcesCard';\nimport { HasComponentsCardProps } from './components/HasComponentsCard';\nimport { HasResourcesCardProps } from './components/HasResourcesCard';\nimport { HasSubcomponentsCardProps } from './components/HasSubcomponentsCard';\nimport { HasSystemsCardProps } from './components/HasSystemsCard';\nimport { RelatedEntitiesCardProps } from './components/RelatedEntitiesCard';\n\n/** @public */\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\n/** @public */\nexport const CatalogIndexPage: (props: DefaultCatalogPageProps) => JSX.Element =\n catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogIndexPage',\n component: () =>\n import('./components/CatalogPage').then(m => m.CatalogPage),\n mountPoint: catalogRouteRef,\n }),\n );\n\n/** @public */\nexport const CatalogEntityPage: () => JSX.Element = catalogPlugin.provide(\n createRoutableExtension({\n name: 'CatalogEntityPage',\n component: () =>\n import('./components/CatalogEntityPage').then(m => m.CatalogEntityPage),\n mountPoint: entityRouteRef,\n }),\n);\n\n/** @public */\nexport const EntityAboutCard: (props: AboutCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityAboutCard',\n component: {\n lazy: () => import('./components/AboutCard').then(m => m.AboutCard),\n },\n }),\n );\n\n/** @public */\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\n/** @public */\nexport const EntityHasSystemsCard: (props: HasSystemsCardProps) => JSX.Element =\n catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasSystemsCard',\n component: {\n lazy: () =>\n import('./components/HasSystemsCard').then(m => m.HasSystemsCard),\n },\n }),\n );\n\n/** @public */\nexport const EntityHasComponentsCard: (\n props: HasComponentsCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasComponentsCard',\n component: {\n lazy: () =>\n import('./components/HasComponentsCard').then(m => m.HasComponentsCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityHasSubcomponentsCard: (\n props: HasSubcomponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityHasResourcesCard: (\n props: HasResourcesCardProps,\n) => JSX.Element = catalogPlugin.provide(\n createComponentExtension({\n name: 'EntityHasResourcesCard',\n component: {\n lazy: () =>\n import('./components/HasResourcesCard').then(m => m.HasResourcesCard),\n },\n }),\n);\n\n/** @public */\nexport const EntityDependsOnComponentsCard: (\n props: DependsOnComponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityDependencyOfComponentsCard: (\n props: DependencyOfComponentsCardProps,\n) => JSX.Element = 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\n/** @public */\nexport const EntityDependsOnResourcesCard: (\n props: DependsOnResourcesCardProps,\n) => JSX.Element = 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/** @public */\nexport const RelatedEntitiesCard: <T extends Entity>(\n props: RelatedEntitiesCardProps<T>,\n) => JSX.Element = 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","capitalize","Edit","makeStyles"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index-7f3caf38.esm.js","sources":["../../src/components/CatalogEntityPage/useEntityFromUrl.ts","../../src/components/CatalogEntityPage/CatalogEntityPage.tsx"],"sourcesContent":["/*\n * Copyright 2022 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n errorApiRef,\n useApi,\n useRouteRefParams,\n} from '@backstage/core-plugin-api';\nimport {\n catalogApiRef,\n EntityLoadingStatus,\n entityRouteRef,\n} from '@backstage/plugin-catalog-react';\nimport { useEffect } from 'react';\nimport { useNavigate } from 'react-router';\nimport useAsyncRetry from 'react-use/lib/useAsyncRetry';\n\nexport const useEntityFromUrl = (): EntityLoadingStatus => {\n const { kind, namespace, name } = useRouteRefParams(entityRouteRef);\n const navigate = useNavigate();\n const errorApi = useApi(errorApiRef);\n const catalogApi = useApi(catalogApiRef);\n\n const {\n value: entity,\n error,\n loading,\n retry: refresh,\n } = useAsyncRetry(\n () => catalogApi.getEntityByName({ kind, namespace, name }),\n [catalogApi, kind, namespace, name],\n );\n\n useEffect(() => {\n if (!name) {\n errorApi.post(new Error('No name provided!'));\n navigate('/');\n }\n }, [errorApi, navigate, error, loading, entity, name]);\n\n return { entity, loading, error, refresh };\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 { Outlet } from 'react-router';\nimport { AsyncEntityProvider } from '@backstage/plugin-catalog-react';\nimport { useEntityFromUrl } from './useEntityFromUrl';\n\n/** @public */\nexport function CatalogEntityPage() {\n return (\n <AsyncEntityProvider {...useEntityFromUrl()}>\n <Outlet />\n </AsyncEntityProvider>\n );\n}\n"],"names":[],"mappings":";;;;;;MA8Ba,mBAAmB,MAA2B;AACzD,QAAM,EAAE,MAAM,WAAW,SAAS,kBAAkB;AACpD,QAAM,WAAW;AACjB,QAAM,WAAW,OAAO;AACxB,QAAM,aAAa,OAAO;AAE1B,QAAM;AAAA,IACJ,OAAO;AAAA,IACP;AAAA,IACA;AAAA,IACA,OAAO;AAAA,MACL,cACF,MAAM,WAAW,gBAAgB,EAAE,MAAM,WAAW,SACpD,CAAC,YAAY,MAAM,WAAW;AAGhC,YAAU,MAAM;AACd,QAAI,CAAC,MAAM;AACT,eAAS,KAAK,IAAI,MAAM;AACxB,eAAS;AAAA;AAAA,KAEV,CAAC,UAAU,UAAU,OAAO,SAAS,QAAQ;AAEhD,SAAO,EAAE,QAAQ,SAAS,OAAO;AAAA;;6BC/BC;AAClC,6CACG,qBAAD;AAAA,OAAyB;AAAA,yCACtB,QAAD;AAAA;;;;"}