diff --git a/.changeset/perfect-chefs-act.md b/.changeset/perfect-chefs-act.md new file mode 100644 index 0000000000..99abbae19d --- /dev/null +++ b/.changeset/perfect-chefs-act.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': minor +--- + +Number of results is now directly added as the field `count` on `useEntityList`. diff --git a/.changeset/rare-worms-sort.md b/.changeset/rare-worms-sort.md new file mode 100644 index 0000000000..6b2175d6d9 --- /dev/null +++ b/.changeset/rare-worms-sort.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': minor +--- + +Adds a title to the `PaginatedCatalogTable` for better visibility on what you're viewing. diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx index c2328a1aef..5f8bf361f1 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx @@ -235,6 +235,7 @@ describe('', () => { await waitFor(() => { expect(result.current.entities.length).toBe(1); }); + expect(result.current.count).toBe(1); await expect(() => waitFor(() => { @@ -251,6 +252,7 @@ describe('', () => { await waitFor(() => { expect(result.current.backendEntities.length).toBeGreaterThan(0); }); + expect(result.current.count).toBe(2); expect(result.current.backendEntities.length).toBe(2); expect(mockCatalogApi.getEntities).toHaveBeenCalledTimes(1); @@ -276,6 +278,8 @@ describe('', () => { }); expect(result.current.backendEntities.length).toBe(2); + expect(result.current.count).toBe(2); + mockCatalogApi.getEntities!.mockRejectedValueOnce('error'); act(() => { result.current.updateFilters({ kind: new EntityKindFilter('api') }); @@ -455,6 +459,8 @@ describe('', () => { orderFields, }); }); + + expect(result.current.count).toBe(10); }); it('returns an error on catalogApi failure', async () => { diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx index abb366a568..1f2300c1c5 100644 --- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx +++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx @@ -108,6 +108,8 @@ export type EntityListContextProps< next?: () => void; prev?: () => void; }; + + count?: number; }; /** @@ -124,6 +126,7 @@ type OutputState = { entities: Entity[]; backendEntities: Entity[]; pageInfo?: QueryEntitiesResponse['pageInfo']; + count?: number; }; /** @@ -223,6 +226,7 @@ export const EntityListProvider = ( backendEntities: response.items, entities: response.items.filter(entityFilter), pageInfo: response.pageInfo, + count: response.totalItems, }); } } else { @@ -243,6 +247,7 @@ export const EntityListProvider = ( backendEntities: response.items, entities: response.items.filter(entityFilter), pageInfo: response.pageInfo, + count: response.totalItems, }); } } @@ -262,16 +267,20 @@ export const EntityListProvider = ( const response = await catalogApi.getEntities({ filter: backendFilter, }); + const entities = response.items.filter(entityFilter); setOutputState({ appliedFilters: requestedFilters, backendEntities: response.items, - entities: response.items.filter(entityFilter), + entities, + count: entities.length, }); } else { + const entities = outputState.backendEntities.filter(entityFilter); setOutputState({ appliedFilters: requestedFilters, backendEntities: outputState.backendEntities, - entities: outputState.backendEntities.filter(entityFilter), + entities, + count: entities.length, }); } } @@ -352,6 +361,7 @@ export const EntityListProvider = ( loading, error, pageInfo, + count: outputState.count, }), [outputState, updateFilters, queryParameters, loading, error, pageInfo], ); diff --git a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx index 7da12d7138..a233499fde 100644 --- a/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/CatalogTable.tsx @@ -88,7 +88,8 @@ export const CatalogTable = (props: CatalogTableProps) => { } = props; const { isStarredEntity, toggleStarredEntity } = useStarredEntities(); const entityListContext = useEntityList(); - const { loading, error, entities, filters, pageInfo } = entityListContext; + const { loading, error, entities, filters, pageInfo, count } = + entityListContext; const enablePagination = !!pageInfo; const tableColumns = useMemo( @@ -175,7 +176,7 @@ export const CatalogTable = (props: CatalogTableProps) => { .filter(s => s) .join(' '); - const title = `${titleDisplay} (${entities.length})`; + const title = `${titleDisplay} (${count})`; const actions = props.actions || defaultActions; const options = { actionsColumnIndex: -1, @@ -216,7 +217,7 @@ export const CatalogTable = (props: CatalogTableProps) => { pageSizeOptions: [20, 50, 100], ...options, }} - title={`${titleDisplay} (${entities.length})`} + title={title} data={rows} actions={actions} subtitle={subtitle} diff --git a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx index 0311cd22ca..fa40756a44 100644 --- a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx @@ -32,11 +32,12 @@ type PaginatedCatalogTableProps = { * @internal */ export function PaginatedCatalogTable(props: PaginatedCatalogTableProps) { - const { columns, data, next, prev } = props; + const { columns, data, next, prev, title, isLoading } = props; const { updateFilters } = useEntityList(); return (