@backstage/plugin-catalog-react 1.7.0-next.1 → 1.7.0-next.3

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,34 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
+ ## 1.7.0-next.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies
8
+ - @backstage/core-components@0.13.2-next.3
9
+ - @backstage/catalog-model@1.4.0-next.1
10
+ - @backstage/catalog-client@1.4.2-next.2
11
+ - @backstage/core-plugin-api@1.5.2-next.0
12
+ - @backstage/errors@1.2.0-next.0
13
+ - @backstage/integration@1.5.0-next.0
14
+ - @backstage/theme@0.4.0-next.1
15
+ - @backstage/types@1.0.2
16
+ - @backstage/version-bridge@1.0.4
17
+ - @backstage/plugin-catalog-common@1.0.14-next.1
18
+ - @backstage/plugin-permission-common@0.7.6-next.0
19
+ - @backstage/plugin-permission-react@0.4.13-next.0
20
+
21
+ ## 1.7.0-next.2
22
+
23
+ ### Patch Changes
24
+
25
+ - d68692aee97e: Make `useRelatedEntities` use `getEntitiesByRefs` under the hood
26
+ - Updated dependencies
27
+ - @backstage/theme@0.4.0-next.1
28
+ - @backstage/core-components@0.13.2-next.2
29
+ - @backstage/core-plugin-api@1.5.2-next.0
30
+ - @backstage/plugin-permission-react@0.4.13-next.0
31
+
3
32
  ## 1.7.0-next.1
4
33
 
5
34
  ### Patch Changes
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react",
3
- "version": "1.7.0-next.1",
3
+ "version": "1.7.0-next.3",
4
4
  "main": "../dist/alpha.esm.js",
5
5
  "module": "../dist/alpha.esm.js",
6
6
  "types": "../dist/alpha.d.ts"
package/dist/index.d.ts CHANGED
@@ -95,8 +95,14 @@ declare const EntityLifecyclePicker: (props: {
95
95
 
96
96
  /** @public */
97
97
  type CatalogReactEntityOwnerPickerClassKey = 'input';
98
+ /**
99
+ * @public
100
+ */
101
+ type EntityOwnerPickerProps = {
102
+ mode?: 'owners-only' | 'all';
103
+ };
98
104
  /** @public */
99
- declare const EntityOwnerPicker: () => JSX.Element | null;
105
+ declare const EntityOwnerPicker: (props?: EntityOwnerPickerProps) => JSX.Element | null;
100
106
 
101
107
  /**
102
108
  * Props for {@link EntityRefLink}.
@@ -569,7 +575,12 @@ declare function useEntityTypeFilter(): {
569
575
  setSelectedTypes: (types: string[]) => void;
570
576
  };
571
577
 
572
- /** @public */
578
+ /**
579
+ * Fetches all entities that appear in the entity's relations, optionally
580
+ * filtered by relation type and kind.
581
+ *
582
+ * @public
583
+ */
573
584
  declare function useRelatedEntities(entity: Entity, relationFilter: {
574
585
  type?: string;
575
586
  kind?: string;
@@ -668,4 +679,4 @@ type EntitySourceLocation = {
668
679
  /** @public */
669
680
  declare function getEntitySourceLocation(entity: Entity, scmIntegrationsApi: ScmIntegrationRegistry): EntitySourceLocation | undefined;
670
681
 
671
- export { AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
682
+ export { AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityOwnerPickerProps, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
package/dist/index.esm.js CHANGED
@@ -8,7 +8,7 @@ import { Select, Link, Progress, ErrorPanel, ResponseErrorPanel, OverflowTooltip
8
8
  import { ANNOTATION_SOURCE_LOCATION, parseLocationRef, stringifyEntityRef, parseEntityRef, RELATION_OWNED_BY, DEFAULT_NAMESPACE, getCompoundEntityRef, isUserEntity, isGroupEntity, RELATION_PART_OF, ANNOTATION_LOCATION, ANNOTATION_ORIGIN_LOCATION } from '@backstage/catalog-model';
9
9
  import { g as getEntityRelations } from './esm/useEntity-de64059a.esm.js';
10
10
  export { A as AsyncEntityProvider, E as EntityProvider, g as getEntityRelations, a as useAsyncEntity, u as useEntity } from './esm/useEntity-de64059a.esm.js';
11
- import { compact, isEqual, groupBy, chunk, debounce } from 'lodash';
11
+ import { compact, isEqual, debounce } from 'lodash';
12
12
  import qs from 'qs';
13
13
  import { useLocation, useNavigate } from 'react-router-dom';
14
14
  import useAsyncFn from 'react-use/lib/useAsyncFn';
@@ -23,7 +23,7 @@ import { Autocomplete, Alert } from '@material-ui/lab';
23
23
  import CheckBoxIcon from '@material-ui/icons/CheckBox';
24
24
  import CheckBoxOutlineBlankIcon from '@material-ui/icons/CheckBoxOutlineBlank';
25
25
  import classNames from 'classnames';
26
- import { useDebouncedEffect } from '@react-hookz/web';
26
+ import { useMountEffect, useDebouncedEffect } from '@react-hookz/web';
27
27
  import PersonIcon from '@material-ui/icons/Person';
28
28
  import GroupIcon from '@material-ui/icons/Group';
29
29
  import get from 'lodash/get';
@@ -38,7 +38,7 @@ import Star from '@material-ui/icons/Star';
38
38
  import StarBorder from '@material-ui/icons/StarBorder';
39
39
  import WorkIcon from '@material-ui/icons/Work';
40
40
  import HelpOutlineIcon from '@material-ui/icons/HelpOutline';
41
- import groupBy$1 from 'lodash/groupBy';
41
+ import groupBy from 'lodash/groupBy';
42
42
  import DialogContentText$1 from '@material-ui/core/DialogContentText';
43
43
  import YAML from 'yaml';
44
44
  import Alert$1 from '@material-ui/lab/Alert';
@@ -489,7 +489,6 @@ function useEntityTypeFilter() {
489
489
  };
490
490
  }
491
491
 
492
- const BATCH_SIZE = 20;
493
492
  function useRelatedEntities(entity, relationFilter) {
494
493
  var _a, _b;
495
494
  const filterByTypeLower = (_a = relationFilter == null ? void 0 : relationFilter.type) == null ? void 0 : _a.toLocaleLowerCase("en-US");
@@ -501,43 +500,16 @@ function useRelatedEntities(entity, relationFilter) {
501
500
  error
502
501
  } = useAsync(async () => {
503
502
  var _a2;
504
- const relations = (_a2 = entity.relations) == null ? void 0 : _a2.map((r) => ({ type: r.type, target: parseEntityRef(r.targetRef) })).filter(
505
- (r) => (!filterByTypeLower || r.type.toLocaleLowerCase("en-US") === filterByTypeLower) && (!filterByKindLower || r.target.kind === filterByKindLower)
503
+ const relations = (_a2 = entity.relations) == null ? void 0 : _a2.filter(
504
+ (r) => (!filterByTypeLower || r.type.toLocaleLowerCase("en-US") === filterByTypeLower) && (!filterByKindLower || parseEntityRef(r.targetRef).kind === filterByKindLower)
506
505
  );
507
- if (!relations) {
506
+ if (!(relations == null ? void 0 : relations.length)) {
508
507
  return [];
509
508
  }
510
- const relationsByKindAndNamespace = Object.values(
511
- groupBy(relations, ({ target }) => {
512
- return `${target.kind}:${target.namespace}`.toLocaleLowerCase("en-US");
513
- })
514
- );
515
- const batchedRelationsByKindAndNamespace = [];
516
- for (const rs of relationsByKindAndNamespace) {
517
- batchedRelationsByKindAndNamespace.push({
518
- // All relations in a group have the same kind and namespace, so its arbitrary which we pick
519
- kind: rs[0].target.kind,
520
- namespace: rs[0].target.namespace,
521
- nameBatches: chunk(
522
- rs.map((r) => r.target.name),
523
- BATCH_SIZE
524
- )
525
- });
526
- }
527
- const results = await Promise.all(
528
- batchedRelationsByKindAndNamespace.flatMap((rs) => {
529
- return rs.nameBatches.map((names) => {
530
- return catalogApi.getEntities({
531
- filter: {
532
- kind: rs.kind,
533
- "metadata.namespace": rs.namespace,
534
- "metadata.name": names
535
- }
536
- });
537
- });
538
- })
539
- );
540
- return results.flatMap((r) => r.items);
509
+ const { items } = await catalogApi.getEntitiesByRefs({
510
+ entityRefs: relations.map((r) => r.targetRef)
511
+ });
512
+ return items.filter((x) => Boolean(x));
541
513
  }, [entity, filterByTypeLower, filterByKindLower]);
542
514
  return {
543
515
  entities,
@@ -903,42 +875,105 @@ function humanizeEntity(entity, defaultName) {
903
875
  return defaultName;
904
876
  }
905
877
 
906
- const useStyles$d = makeStyles(
907
- {
908
- input: {}
909
- },
910
- {
911
- name: "CatalogReactEntityOwnerPicker"
878
+ function useFacetsEntities({ enabled }) {
879
+ const catalogApi = useApi(catalogApiRef);
880
+ const [facetsPromise] = useState(async () => {
881
+ if (!enabled) {
882
+ return [];
883
+ }
884
+ const facet = "relations.ownedBy";
885
+ return catalogApi.getEntityFacets({ facets: [facet] }).then(
886
+ (response) => response.facets[facet].map((e) => e.value).map((ref) => {
887
+ const { kind, name, namespace } = parseEntityRef(ref);
888
+ return {
889
+ apiVersion: "backstage.io/v1beta1",
890
+ kind,
891
+ metadata: { name, namespace }
892
+ };
893
+ }).sort(
894
+ (a, b) => (a.metadata.namespace || "").localeCompare(
895
+ b.metadata.namespace || "",
896
+ "en-US"
897
+ ) || a.metadata.name.localeCompare(b.metadata.name, "en-US") || a.kind.localeCompare(b.kind, "en-US")
898
+ )
899
+ ).catch(() => []);
900
+ });
901
+ return useAsyncFn(
902
+ async (request, options) => {
903
+ var _a;
904
+ const facets = await facetsPromise;
905
+ if (!facets) {
906
+ return {
907
+ items: []
908
+ };
909
+ }
910
+ const limit = (_a = options == null ? void 0 : options.limit) != null ? _a : 20;
911
+ const { text, start } = decodeCursor(request);
912
+ const filteredRefs = facets.filter((e) => filterEntity(text, e));
913
+ const end = start + limit;
914
+ return {
915
+ items: filteredRefs.slice(0, end),
916
+ ...encodeCursor({
917
+ entities: filteredRefs,
918
+ limit: end,
919
+ payload: {
920
+ text,
921
+ start: end
922
+ }
923
+ })
924
+ };
925
+ },
926
+ [facetsPromise],
927
+ { loading: true, value: { items: [] } }
928
+ );
929
+ }
930
+ function decodeCursor(request) {
931
+ if (isFacetsResponse(request) && request.cursor) {
932
+ return JSON.parse(atob(request.cursor));
912
933
  }
913
- );
914
- const icon$1 = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
915
- const checkedIcon$1 = /* @__PURE__ */ React.createElement(CheckBoxIcon, { fontSize: "small" });
916
- const EntityOwnerPicker = () => {
917
- var _a, _b, _c;
918
- const classes = useStyles$d();
919
- const {
920
- updateFilters,
921
- filters,
922
- queryParameters: { owners: ownersParameter }
923
- } = useEntityList();
934
+ return {
935
+ text: request.text || "",
936
+ start: 0
937
+ };
938
+ }
939
+ function isFacetsResponse(request) {
940
+ return !!request.cursor;
941
+ }
942
+ function encodeCursor({
943
+ entities,
944
+ limit,
945
+ payload
946
+ }) {
947
+ if (entities.length > limit) {
948
+ return { cursor: btoa(JSON.stringify(payload)) };
949
+ }
950
+ return {};
951
+ }
952
+ function filterEntity(text, entity) {
953
+ var _a;
954
+ const normalizedText = text.trim();
955
+ return entity.kind.includes(normalizedText) || ((_a = entity.metadata.namespace) == null ? void 0 : _a.includes(normalizedText)) || entity.metadata.name.includes(normalizedText);
956
+ }
957
+
958
+ function useQueryEntities() {
924
959
  const catalogApi = useApi(catalogApiRef);
925
- const [text, setText] = useState("");
926
- const [{ value, loading }, handleFetch] = useAsyncFn(
927
- async (request) => {
960
+ return useAsyncFn(
961
+ async (request, options) => {
962
+ var _a;
928
963
  const initialRequest = request;
929
964
  const cursorRequest = request;
930
- const limit = 20;
965
+ const limit = (_a = options == null ? void 0 : options.limit) != null ? _a : 20;
931
966
  if (cursorRequest.cursor) {
932
- const response = await catalogApi.queryEntities({
967
+ const response2 = await catalogApi.queryEntities({
933
968
  cursor: cursorRequest.cursor,
934
969
  limit
935
970
  });
936
971
  return {
937
- ...response,
938
- items: [...cursorRequest.prev, ...response.items]
972
+ cursor: response2.pageInfo.nextCursor,
973
+ items: [...cursorRequest.items, ...response2.items]
939
974
  };
940
975
  }
941
- return catalogApi.queryEntities({
976
+ const response = await catalogApi.queryEntities({
942
977
  fullTextFilter: {
943
978
  term: initialRequest.text || "",
944
979
  fields: [
@@ -952,11 +987,84 @@ const EntityOwnerPicker = () => {
952
987
  orderFields: [{ field: "metadata.name", order: "asc" }],
953
988
  limit
954
989
  });
990
+ return {
991
+ cursor: response.pageInfo.nextCursor,
992
+ items: response.items
993
+ };
955
994
  },
956
- [text]
995
+ [],
996
+ { loading: true }
957
997
  );
958
- useDebouncedEffect(() => handleFetch({ text }), [text], 250);
959
- const availableOwners = (value == null ? void 0 : value.items) || [];
998
+ }
999
+
1000
+ function useFetchEntities({
1001
+ mode,
1002
+ initialSelectedOwnersRefs
1003
+ }) {
1004
+ const isOwnersOnlyMode = mode === "owners-only";
1005
+ const queryEntitiesResponse = useQueryEntities();
1006
+ const facetsEntitiesResponse = useFacetsEntities({
1007
+ enabled: isOwnersOnlyMode
1008
+ });
1009
+ const [state, handleFetch] = isOwnersOnlyMode ? facetsEntitiesResponse : queryEntitiesResponse;
1010
+ return [
1011
+ state,
1012
+ handleFetch,
1013
+ useSelectedOwners({
1014
+ enabled: !isOwnersOnlyMode,
1015
+ initialSelectedOwnersRefs
1016
+ })
1017
+ ];
1018
+ }
1019
+ function useSelectedOwners({
1020
+ enabled,
1021
+ initialSelectedOwnersRefs
1022
+ }) {
1023
+ const allEntities = useRef({});
1024
+ const catalogApi = useApi(catalogApiRef);
1025
+ const [, handleFetch] = useAsyncFn(async () => {
1026
+ const initialSelectedEntities = await catalogApi.getEntitiesByRefs({
1027
+ entityRefs: initialSelectedOwnersRefs
1028
+ });
1029
+ initialSelectedEntities.items.forEach((e) => {
1030
+ if (e) {
1031
+ allEntities.current[stringifyEntityRef(e)] = e;
1032
+ }
1033
+ });
1034
+ }, []);
1035
+ useMountEffect(() => {
1036
+ if (enabled && initialSelectedOwnersRefs.length > 0) {
1037
+ handleFetch();
1038
+ }
1039
+ });
1040
+ return {
1041
+ getEntity: (entityRef) => allEntities.current[entityRef],
1042
+ setEntity: (entity) => {
1043
+ allEntities.current[stringifyEntityRef(entity)] = entity;
1044
+ }
1045
+ };
1046
+ }
1047
+
1048
+ const useStyles$d = makeStyles(
1049
+ {
1050
+ input: {}
1051
+ },
1052
+ {
1053
+ name: "CatalogReactEntityOwnerPicker"
1054
+ }
1055
+ );
1056
+ const icon$1 = /* @__PURE__ */ React.createElement(CheckBoxOutlineBlankIcon, { fontSize: "small" });
1057
+ const checkedIcon$1 = /* @__PURE__ */ React.createElement(CheckBoxIcon, { fontSize: "small" });
1058
+ const EntityOwnerPicker = (props) => {
1059
+ var _a, _b, _c;
1060
+ const classes = useStyles$d();
1061
+ const { mode = "owners-only" } = props || {};
1062
+ const {
1063
+ updateFilters,
1064
+ filters,
1065
+ queryParameters: { owners: ownersParameter }
1066
+ } = useEntityList();
1067
+ const [text, setText] = useState("");
960
1068
  const queryParamOwners = useMemo(
961
1069
  () => [ownersParameter].flat().filter(Boolean),
962
1070
  [ownersParameter]
@@ -964,7 +1072,12 @@ const EntityOwnerPicker = () => {
964
1072
  const [selectedOwners, setSelectedOwners] = useState(
965
1073
  queryParamOwners.length ? queryParamOwners : (_b = (_a = filters.owners) == null ? void 0 : _a.values) != null ? _b : []
966
1074
  );
967
- const { getEntity, setEntity } = useSelectedOwners(selectedOwners);
1075
+ const [{ value, loading }, handleFetch, cache] = useFetchEntities({
1076
+ mode,
1077
+ initialSelectedOwnersRefs: selectedOwners
1078
+ });
1079
+ useDebouncedEffect(() => handleFetch({ text }), [text, handleFetch], 250);
1080
+ const availableOwners = (value == null ? void 0 : value.items) || [];
968
1081
  useEffect(() => {
969
1082
  if (queryParamOwners.length) {
970
1083
  const filter = new EntityOwnerFilter(queryParamOwners);
@@ -996,8 +1109,11 @@ const EntityOwnerPicker = () => {
996
1109
  return o === v;
997
1110
  },
998
1111
  getOptionLabel: (o) => {
999
- const entity = typeof o === "string" ? getEntity(o) || o : o;
1000
- return typeof entity === "string" ? entity : humanizeEntity(entity, entity.metadata.name);
1112
+ const entity = typeof o === "string" ? cache.getEntity(o) || parseEntityRef(o, {
1113
+ defaultKind: "group",
1114
+ defaultNamespace: "default"
1115
+ }) : o;
1116
+ return humanizeEntity(entity, humanizeEntityRef(entity));
1001
1117
  },
1002
1118
  onChange: (_, owners) => {
1003
1119
  setText("");
@@ -1005,7 +1121,7 @@ const EntityOwnerPicker = () => {
1005
1121
  owners.map((e) => {
1006
1122
  const entityRef = typeof e === "string" ? e : stringifyEntityRef(e);
1007
1123
  if (typeof e !== "string") {
1008
- setEntity(e);
1124
+ cache.setEntity(e);
1009
1125
  }
1010
1126
  return entityRef;
1011
1127
  })
@@ -1013,7 +1129,7 @@ const EntityOwnerPicker = () => {
1013
1129
  },
1014
1130
  filterOptions: (x) => x,
1015
1131
  renderOption: (entity, { selected }) => {
1016
- const isGroup = entity.kind === "Group";
1132
+ const isGroup = entity.kind.toLocaleLowerCase("en-US") === "group";
1017
1133
  return /* @__PURE__ */ React.createElement(
1018
1134
  FormControlLabel,
1019
1135
  {
@@ -1026,7 +1142,10 @@ const EntityOwnerPicker = () => {
1026
1142
  }
1027
1143
  ),
1028
1144
  onClick: (event) => event.preventDefault(),
1029
- label: /* @__PURE__ */ React.createElement(Box, { display: "flex", flexWrap: "wrap", alignItems: "center" }, isGroup ? /* @__PURE__ */ React.createElement(GroupIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(PersonIcon, { fontSize: "small" }), "\xA0", humanizeEntity(entity, entity.metadata.name))
1145
+ label: /* @__PURE__ */ React.createElement(Box, { display: "flex", flexWrap: "wrap", alignItems: "center" }, isGroup ? /* @__PURE__ */ React.createElement(GroupIcon, { fontSize: "small" }) : /* @__PURE__ */ React.createElement(PersonIcon, { fontSize: "small" }), "\xA0", humanizeEntity(
1146
+ entity,
1147
+ humanizeEntityRef(entity, { defaultKind: entity.kind })
1148
+ ))
1030
1149
  }
1031
1150
  );
1032
1151
  },
@@ -1049,11 +1168,8 @@ const EntityOwnerPicker = () => {
1049
1168
  const hasReachedEnd = Math.abs(
1050
1169
  element.scrollHeight - element.clientHeight - element.scrollTop
1051
1170
  ) < 1;
1052
- if (hasReachedEnd && (value == null ? void 0 : value.pageInfo.nextCursor)) {
1053
- handleFetch({
1054
- cursor: value.pageInfo.nextCursor,
1055
- prev: value.items
1056
- });
1171
+ if (hasReachedEnd && (value == null ? void 0 : value.cursor)) {
1172
+ handleFetch({ items: value.items, cursor: value.cursor });
1057
1173
  }
1058
1174
  },
1059
1175
  "data-testid": "owner-picker-listbox"
@@ -1061,29 +1177,6 @@ const EntityOwnerPicker = () => {
1061
1177
  }
1062
1178
  )));
1063
1179
  };
1064
- function useSelectedOwners(initialSelectedOwnersRefs) {
1065
- const allEntities = useRef({});
1066
- const catalogApi = useApi(catalogApiRef);
1067
- useAsync(async () => {
1068
- if (initialSelectedOwnersRefs.length === 0) {
1069
- return;
1070
- }
1071
- const initialSelectedEntities = await catalogApi.getEntitiesByRefs({
1072
- entityRefs: initialSelectedOwnersRefs
1073
- });
1074
- initialSelectedEntities.items.forEach((e) => {
1075
- if (e) {
1076
- allEntities.current[stringifyEntityRef(e)] = e;
1077
- }
1078
- });
1079
- }, []);
1080
- return {
1081
- getEntity: (entityRef) => allEntities.current[entityRef],
1082
- setEntity: (entity) => {
1083
- allEntities.current[stringifyEntityRef(entity)] = entity;
1084
- }
1085
- };
1086
- }
1087
1180
 
1088
1181
  const entityRouteRef = getOrCreateGlobalSingleton(
1089
1182
  "catalog:entity-route-ref",
@@ -1996,7 +2089,7 @@ function OverviewPage(props) {
1996
2089
  relations = [],
1997
2090
  status = {}
1998
2091
  } = props.entity;
1999
- const groupedRelations = groupBy$1(
2092
+ const groupedRelations = groupBy(
2000
2093
  sortBy(relations, (r) => r.targetRef),
2001
2094
  "type"
2002
2095
  );