@backstage/plugin-catalog-react 1.9.1 → 1.9.2-next.0

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,12 +1,27 @@
1
1
  # @backstage/plugin-catalog-react
2
2
 
3
- ## 1.9.1
3
+ ## 1.9.2-next.0
4
4
 
5
5
  ### Patch Changes
6
6
 
7
- - ceebf2ca4ba7: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended.
7
+ - 8587f067d2: Added pagination support to `EntityListProvider`.
8
+ - aaa6fb3bc9: Minor updates for TypeScript 5.2.2+ compatibility
9
+ - 4d9e3b39e4: Register component overrides in the global `OverrideComponentNameToClassKeys` provided by `@backstage/theme`. This will in turn will provide component style override types for `createUnifiedTheme`.
10
+ - eee0ff2946: Fixed a issue where `CatalogPage` wasn't using the chosen `initiallySelectedFilter` as intended.
8
11
  - Updated dependencies
9
- - @backstage/integration-react@1.1.21
12
+ - @backstage/core-plugin-api@1.8.1-next.0
13
+ - @backstage/core-components@0.13.9-next.0
14
+ - @backstage/theme@0.5.0-next.0
15
+ - @backstage/frontend-plugin-api@0.3.1-next.0
16
+ - @backstage/integration-react@1.1.22-next.0
17
+ - @backstage/plugin-permission-react@0.4.18-next.0
18
+ - @backstage/catalog-client@1.4.6
19
+ - @backstage/catalog-model@1.4.3
20
+ - @backstage/errors@1.2.3
21
+ - @backstage/types@1.1.1
22
+ - @backstage/version-bridge@1.0.7
23
+ - @backstage/plugin-catalog-common@1.0.18
24
+ - @backstage/plugin-permission-common@0.7.10
10
25
 
11
26
  ## 1.9.0
12
27
 
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/plugin-catalog-react",
3
- "version": "1.9.1",
3
+ "version": "1.9.2-next.0",
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
@@ -678,17 +678,29 @@ type EntityListContextProps<EntityFilters extends DefaultEntityFilters = Default
678
678
  queryParameters: Partial<Record<keyof EntityFilters, string | string[]>>;
679
679
  loading: boolean;
680
680
  error?: Error;
681
+ pageInfo?: {
682
+ next?: () => void;
683
+ prev?: () => void;
684
+ };
681
685
  };
682
686
  /**
683
687
  * Creates new context for entity listing and filtering.
684
688
  * @public
685
689
  */
686
690
  declare const EntityListContext: React.Context<EntityListContextProps<any> | undefined>;
691
+ /**
692
+ * @public
693
+ */
694
+ type EntityListProviderProps = PropsWithChildren<{
695
+ pagination?: boolean | {
696
+ limit?: number;
697
+ };
698
+ }>;
687
699
  /**
688
700
  * Provides entities and filters for a catalog listing.
689
701
  * @public
690
702
  */
691
- declare const EntityListProvider: <EntityFilters extends DefaultEntityFilters>(props: PropsWithChildren<{}>) => React.JSX.Element;
703
+ declare const EntityListProvider: <EntityFilters extends DefaultEntityFilters>(props: EntityListProviderProps) => React.JSX.Element;
692
704
  /**
693
705
  * Hook for interacting with the entity list context provided by the {@link EntityListProvider}.
694
706
  * @public
@@ -883,6 +895,10 @@ type CatalogReactComponentsNameToClassKey = {
883
895
  type BackstageOverrides = Overrides & {
884
896
  [Name in keyof CatalogReactComponentsNameToClassKey]?: Partial<StyleRules<CatalogReactComponentsNameToClassKey[Name]>>;
885
897
  };
898
+ declare module '@backstage/theme' {
899
+ interface OverrideComponentNameToClassKeys extends CatalogReactComponentsNameToClassKey {
900
+ }
901
+ }
886
902
 
887
903
  /**
888
904
  * Get the related entity references.
@@ -901,4 +917,4 @@ type EntitySourceLocation = {
901
917
  /** @public */
902
918
  declare function getEntitySourceLocation(entity: Entity, scmIntegrationsApi: typeof scmIntegrationsApiRef.T): EntitySourceLocation | undefined;
903
919
 
904
- export { AllowedEntityFilters, AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityDisplayNameClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityAutocompletePicker, EntityAutocompletePickerProps, EntityDisplayName, EntityDisplayNameProps, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityOwnerPickerProps, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntityRefPresentation, EntityRefPresentationSnapshot, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, EntityUserFilter, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MissingAnnotationEmptyState, MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
920
+ export { AllowedEntityFilters, AsyncEntityProvider, AsyncEntityProviderProps, BackstageOverrides, CatalogFilterLayout, CatalogReactComponentsNameToClassKey, CatalogReactEntityDisplayNameClassKey, CatalogReactEntityLifecyclePickerClassKey, CatalogReactEntityNamespacePickerClassKey, CatalogReactEntityOwnerPickerClassKey, CatalogReactEntityProcessingStatusPickerClassKey, CatalogReactEntitySearchBarClassKey, CatalogReactEntityTagPickerClassKey, CatalogReactUserListPickerClassKey, DefaultEntityFilters, EntityAutocompletePicker, EntityAutocompletePickerProps, EntityDisplayName, EntityDisplayNameProps, EntityErrorFilter, EntityFilter, EntityKindFilter, EntityKindPicker, EntityKindPickerProps, EntityLifecycleFilter, EntityLifecyclePicker, EntityListContext, EntityListContextProps, EntityListProvider, EntityListProviderProps, EntityLoadingStatus, EntityNamespaceFilter, EntityNamespacePicker, EntityOrphanFilter, EntityOwnerFilter, EntityOwnerPicker, EntityOwnerPickerProps, EntityPeekAheadPopover, EntityPeekAheadPopoverProps, EntityPresentationApi, EntityProcessingStatusPicker, EntityProvider, EntityProviderProps, EntityRefLink, EntityRefLinkProps, EntityRefLinks, EntityRefLinksProps, EntityRefPresentation, EntityRefPresentationSnapshot, EntitySearchBar, EntitySourceLocation, EntityTable, EntityTableProps, EntityTagFilter, EntityTagPicker, EntityTagPickerProps, EntityTextFilter, EntityTypeFilter, EntityTypePicker, EntityTypePickerProps, EntityUserFilter, FavoriteEntity, FavoriteEntityProps, InspectEntityDialog, MissingAnnotationEmptyState, MissingAnnotationEmptyStateClassKey, MockEntityListContextProvider, MockStarredEntitiesApi, StarredEntitiesApi, UnregisterEntityDialog, UnregisterEntityDialogProps, UserListFilter, UserListFilterKind, UserListPicker, UserListPickerProps, catalogApiRef, columnFactories, defaultEntityPresentation, entityPresentationApiRef, entityRouteParams, entityRouteRef, getEntityRelations, getEntitySourceLocation, humanizeEntityRef, starredEntitiesApiRef, useAsyncEntity, useEntity, useEntityList, useEntityOwnership, useEntityPresentation, useEntityTypeFilter, useRelatedEntities, useStarredEntities, useStarredEntity };
package/dist/index.esm.js CHANGED
@@ -561,21 +561,26 @@ const EntityListProvider = (props) => {
561
561
  {}
562
562
  );
563
563
  const location = useLocation();
564
- const queryParameters = useMemo(
565
- () => {
566
- var _a;
567
- return (_a = qs.parse(location.search, {
568
- ignoreQueryPrefix: true
569
- }).filters) != null ? _a : {};
570
- },
571
- [location]
572
- );
564
+ const enablePagination = props.pagination === true || typeof props.pagination === "object";
565
+ const limit = props.pagination && typeof props.pagination === "object" && typeof props.pagination.limit === "number" ? props.pagination.limit : 20;
566
+ const { queryParameters, cursor: initialCursor } = useMemo(() => {
567
+ var _a;
568
+ const parsed = qs.parse(location.search, {
569
+ ignoreQueryPrefix: true
570
+ });
571
+ return {
572
+ queryParameters: (_a = parsed.filters) != null ? _a : {},
573
+ cursor: typeof parsed.cursor === "string" ? parsed.cursor : void 0
574
+ };
575
+ }, [location]);
576
+ const [cursor, setCursor] = useState(initialCursor);
573
577
  const [outputState, setOutputState] = useState(
574
578
  () => {
575
579
  return {
576
580
  appliedFilters: {},
577
581
  entities: [],
578
- backendEntities: []
582
+ backendEntities: [],
583
+ pageInfo: enablePagination ? {} : void 0
579
584
  };
580
585
  }
581
586
  );
@@ -583,11 +588,6 @@ const EntityListProvider = (props) => {
583
588
  async () => {
584
589
  var _a;
585
590
  const compacted = compact(Object.values(requestedFilters));
586
- const entityFilter = reduceEntityFilters(compacted);
587
- const backendFilter = reduceBackendCatalogFilters(compacted);
588
- const previousBackendFilter = reduceBackendCatalogFilters(
589
- compact(Object.values(outputState.appliedFilters))
590
- );
591
591
  const queryParams = Object.keys(requestedFilters).reduce(
592
592
  (params, key) => {
593
593
  const filter = requestedFilters[key];
@@ -598,40 +598,91 @@ const EntityListProvider = (props) => {
598
598
  },
599
599
  {}
600
600
  );
601
- if (!isEqual(previousBackendFilter, backendFilter)) {
602
- const response = await catalogApi.getEntities({
603
- filter: backendFilter
604
- });
605
- setOutputState({
606
- appliedFilters: requestedFilters,
607
- backendEntities: response.items,
608
- entities: response.items.filter(entityFilter)
609
- });
601
+ if (enablePagination) {
602
+ if (cursor) {
603
+ if (cursor !== outputState.appliedCursor) {
604
+ const entityFilter = reduceEntityFilters(compacted);
605
+ const response = await catalogApi.queryEntities({
606
+ cursor,
607
+ limit
608
+ });
609
+ setOutputState({
610
+ appliedFilters: requestedFilters,
611
+ appliedCursor: cursor,
612
+ backendEntities: response.items,
613
+ entities: response.items.filter(entityFilter),
614
+ pageInfo: response.pageInfo
615
+ });
616
+ }
617
+ } else {
618
+ const entityFilter = reduceEntityFilters(compacted);
619
+ const backendFilter = reduceCatalogFilters(compacted);
620
+ const previousBackendFilter = reduceCatalogFilters(
621
+ compact(Object.values(outputState.appliedFilters))
622
+ );
623
+ if (!isEqual(previousBackendFilter, backendFilter)) {
624
+ const response = await catalogApi.queryEntities({
625
+ filter: backendFilter,
626
+ limit,
627
+ orderFields: [{ field: "metadata.name", order: "asc" }]
628
+ });
629
+ setOutputState({
630
+ appliedFilters: requestedFilters,
631
+ backendEntities: response.items,
632
+ entities: response.items.filter(entityFilter),
633
+ pageInfo: response.pageInfo
634
+ });
635
+ }
636
+ }
610
637
  } else {
611
- setOutputState({
612
- appliedFilters: requestedFilters,
613
- backendEntities: outputState.backendEntities,
614
- entities: outputState.backendEntities.filter(entityFilter)
615
- });
638
+ const entityFilter = reduceEntityFilters(compacted);
639
+ const backendFilter = reduceBackendCatalogFilters(compacted);
640
+ const previousBackendFilter = reduceBackendCatalogFilters(
641
+ compact(Object.values(outputState.appliedFilters))
642
+ );
643
+ if (!isEqual(previousBackendFilter, backendFilter)) {
644
+ const response = await catalogApi.getEntities({
645
+ filter: backendFilter
646
+ });
647
+ setOutputState({
648
+ appliedFilters: requestedFilters,
649
+ backendEntities: response.items,
650
+ entities: response.items.filter(entityFilter)
651
+ });
652
+ } else {
653
+ setOutputState({
654
+ appliedFilters: requestedFilters,
655
+ backendEntities: outputState.backendEntities,
656
+ entities: outputState.backendEntities.filter(entityFilter)
657
+ });
658
+ }
616
659
  }
617
660
  if (isMounted()) {
618
661
  const oldParams = qs.parse(location.search, {
619
662
  ignoreQueryPrefix: true
620
663
  });
621
664
  const newParams = qs.stringify(
622
- { ...oldParams, filters: queryParams },
665
+ { ...oldParams, filters: queryParams, cursor },
623
666
  { addQueryPrefix: true, arrayFormat: "repeat" }
624
667
  );
625
668
  const newUrl = `${window.location.pathname}${newParams}`;
626
669
  (_a = window.history) == null ? void 0 : _a.replaceState(null, document.title, newUrl);
627
670
  }
628
671
  },
629
- [catalogApi, queryParameters, requestedFilters, outputState],
672
+ [
673
+ catalogApi,
674
+ queryParameters,
675
+ requestedFilters,
676
+ outputState,
677
+ cursor,
678
+ enablePagination
679
+ ],
630
680
  { loading: true }
631
681
  );
632
- useDebounce(refresh, 10, [requestedFilters]);
682
+ useDebounce(refresh, 10, [requestedFilters, cursor]);
633
683
  const updateFilters = useCallback(
634
684
  (update) => {
685
+ setCursor(void 0);
635
686
  setRequestedFilters((prevFilters) => {
636
687
  const newFilters = typeof update === "function" ? update(prevFilters) : update;
637
688
  return { ...prevFilters, ...newFilters };
@@ -639,6 +690,18 @@ const EntityListProvider = (props) => {
639
690
  },
640
691
  []
641
692
  );
693
+ const pageInfo = useMemo(() => {
694
+ var _a, _b;
695
+ if (!enablePagination) {
696
+ return void 0;
697
+ }
698
+ const prevCursor = (_a = outputState.pageInfo) == null ? void 0 : _a.prevCursor;
699
+ const nextCursor = (_b = outputState.pageInfo) == null ? void 0 : _b.nextCursor;
700
+ return {
701
+ prev: prevCursor ? () => setCursor(prevCursor) : void 0,
702
+ next: nextCursor ? () => setCursor(nextCursor) : void 0
703
+ };
704
+ }, [enablePagination, outputState.pageInfo]);
642
705
  const value = useMemo(
643
706
  () => ({
644
707
  filters: outputState.appliedFilters,
@@ -647,9 +710,10 @@ const EntityListProvider = (props) => {
647
710
  updateFilters,
648
711
  queryParameters,
649
712
  loading,
650
- error
713
+ error,
714
+ pageInfo
651
715
  }),
652
- [outputState, updateFilters, queryParameters, loading, error]
716
+ [outputState, updateFilters, queryParameters, loading, error, pageInfo]
653
717
  );
654
718
  return /* @__PURE__ */ React.createElement(EntityListContext.Provider, { value }, props.children);
655
719
  };