diff --git a/.changeset/warm-dancers-battle.md b/.changeset/warm-dancers-battle.md
new file mode 100644
index 0000000000..8aa3f765e8
--- /dev/null
+++ b/.changeset/warm-dancers-battle.md
@@ -0,0 +1,5 @@
+---
+'@backstage/plugin-catalog-react': patch
+---
+
+Fixed catalog filter "all" not appearing as selected when set as the initially selected filter.
diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
index 8ef1707bb1..f7090f330b 100644
--- a/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
+++ b/plugins/catalog-react/src/hooks/useEntityListProvider.test.tsx
@@ -498,6 +498,29 @@ describe('', () => {
});
});
+ it('applies frontend-only filters without refetching', async () => {
+ const { result } = renderHook(() => useEntityList(), {
+ wrapper: createWrapper({ pagination }),
+ });
+
+ await waitFor(() => {
+ expect(result.current.backendEntities.length).toBe(2);
+ expect(result.current.filters.kind?.value).toBe('component');
+ });
+
+ act(() =>
+ result.current.updateFilters({
+ user: EntityUserFilter.all(),
+ }),
+ );
+
+ await waitFor(() => {
+ expect(result.current.filters.user?.value).toBe('all');
+ expect(result.current.entities.length).toBe(2);
+ });
+ expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1);
+ });
+
it('resolves query param filter values', async () => {
const query = qs.stringify({
filters: { kind: 'component', type: 'service' },
@@ -801,6 +824,29 @@ describe(``, () => {
});
});
+ it('applies frontend-only filters without refetching', async () => {
+ const { result } = renderHook(() => useEntityList(), {
+ wrapper: createWrapper({ pagination }),
+ });
+
+ await waitFor(() => {
+ expect(result.current.backendEntities.length).toBe(2);
+ expect(result.current.filters.kind?.value).toBe('component');
+ });
+
+ act(() =>
+ result.current.updateFilters({
+ user: EntityUserFilter.all(),
+ }),
+ );
+
+ await waitFor(() => {
+ expect(result.current.filters.user?.value).toBe('all');
+ expect(result.current.entities.length).toBe(2);
+ });
+ expect(mockCatalogApi.queryEntities).toHaveBeenCalledTimes(1);
+ });
+
it('resolves query param filter values', async () => {
const query = qs.stringify({
filters: { kind: 'component', type: 'service' },
diff --git a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx
index 319740e70e..8c4927ad0a 100644
--- a/plugins/catalog-react/src/hooks/useEntityListProvider.tsx
+++ b/plugins/catalog-react/src/hooks/useEntityListProvider.tsx
@@ -249,11 +249,11 @@ export const EntityListProvider = (
? { ...requestedFilters, owners: undefined }
: requestedFilters;
const compacted = compact(Object.values(adjustedFilters));
+ const entityFilter = reduceEntityFilters(compacted);
if (paginationMode !== 'none') {
if (cursor) {
if (cursor !== outputState.appliedCursor) {
- const entityFilter = reduceEntityFilters(compacted);
const response = await catalogApi.queryEntities({
cursor,
limit,
@@ -267,58 +267,42 @@ export const EntityListProvider = (
totalItems: response.totalItems,
};
}
- } else {
- const entityFilter = reduceEntityFilters(compacted);
- const backendFilter = reduceCatalogFilters(compacted);
- const previousBackendFilter = reduceCatalogFilters(
- compact(Object.values(outputState.appliedFilters)),
- );
-
- if (
- (paginationMode === 'offset' &&
- (outputState.limit !== limit || outputState.offset !== offset)) ||
- !isEqual(previousBackendFilter, backendFilter)
- ) {
- const response = await catalogApi.queryEntities({
- ...backendFilter,
- limit,
- offset,
- });
- return {
- appliedFilters: requestedFilters,
- backendEntities: response.items,
- entities: response.items.filter(entityFilter),
- pageInfo: response.pageInfo,
- totalItems: response.totalItems,
- limit,
- offset,
- };
- }
+ const entities = outputState.backendEntities.filter(entityFilter);
+ return {
+ appliedFilters: requestedFilters,
+ appliedCursor: outputState.appliedCursor,
+ backendEntities: outputState.backendEntities,
+ entities,
+ pageInfo: outputState.pageInfo,
+ totalItems: outputState.totalItems,
+ limit: outputState.limit,
+ offset: outputState.offset,
+ };
}
- } else {
- const entityFilter = reduceEntityFilters(compacted);
- const backendFilter = reduceBackendCatalogFilters(compacted);
- const { orderFields } = reduceCatalogFilters(compacted);
- const previousBackendFilter = reduceBackendCatalogFilters(
+
+ const backendFilter = reduceCatalogFilters(compacted);
+ const previousBackendFilter = reduceCatalogFilters(
compact(Object.values(outputState.appliedFilters)),
);
- // TODO(mtlewis): currently entities will never be requested unless
- // there's at least one filter, we should allow an initial request
- // to happen with no filters.
- if (!isEqual(previousBackendFilter, backendFilter)) {
- // TODO(timbonicus): should limit fields here, but would need filter
- // fields + table columns
- const response = await catalogApi.getEntities({
- filter: backendFilter,
- order: orderFields,
+ if (
+ (paginationMode === 'offset' &&
+ (outputState.limit !== limit || outputState.offset !== offset)) ||
+ !isEqual(previousBackendFilter, backendFilter)
+ ) {
+ const response = await catalogApi.queryEntities({
+ ...backendFilter,
+ limit,
+ offset,
});
- const entities = response.items.filter(entityFilter);
return {
appliedFilters: requestedFilters,
backendEntities: response.items,
- entities,
- totalItems: entities.length,
+ entities: response.items.filter(entityFilter),
+ pageInfo: response.pageInfo,
+ totalItems: response.totalItems,
+ limit,
+ offset,
};
}
const entities = outputState.backendEntities.filter(entityFilter);
@@ -326,10 +310,44 @@ export const EntityListProvider = (
appliedFilters: requestedFilters,
backendEntities: outputState.backendEntities,
entities,
+ pageInfo: outputState.pageInfo,
+ totalItems: outputState.totalItems,
+ limit: outputState.limit,
+ offset: outputState.offset,
+ };
+ }
+
+ const backendFilter = reduceBackendCatalogFilters(compacted);
+ const { orderFields } = reduceCatalogFilters(compacted);
+ const previousBackendFilter = reduceBackendCatalogFilters(
+ compact(Object.values(outputState.appliedFilters)),
+ );
+
+ // TODO(mtlewis): currently entities will never be requested unless
+ // there's at least one filter, we should allow an initial request
+ // to happen with no filters.
+ if (!isEqual(previousBackendFilter, backendFilter)) {
+ // TODO(timbonicus): should limit fields here, but would need filter
+ // fields + table columns
+ const response = await catalogApi.getEntities({
+ filter: backendFilter,
+ order: orderFields,
+ });
+ const entities = response.items.filter(entityFilter);
+ return {
+ appliedFilters: requestedFilters,
+ backendEntities: response.items,
+ entities,
totalItems: entities.length,
};
}
- return undefined;
+ const entities = outputState.backendEntities.filter(entityFilter);
+ return {
+ appliedFilters: requestedFilters,
+ backendEntities: outputState.backendEntities,
+ entities,
+ totalItems: entities.length,
+ };
},
[
catalogApi,