diff --git a/.changeset/great-hounds-allow.md b/.changeset/great-hounds-allow.md new file mode 100644 index 0000000000..54405fcf94 --- /dev/null +++ b/.changeset/great-hounds-allow.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Updated `CatalogKindHeader` to respond to external changes to query parameters in the URL, such as two sidebar links that apply different catalog filters. diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx index 45d42d0ea6..a7dc18eae2 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.test.tsx @@ -135,4 +135,38 @@ describe('', () => { kind: new EntityKindFilter('template'), }); }); + + it('responds to external queryParameters changes', async () => { + const updateFilters = jest.fn(); + const rendered = await renderWithEffects( + + + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + kind: new EntityKindFilter('components'), + }); + rendered.rerender( + + + + + , + ); + expect(updateFilters).toHaveBeenLastCalledWith({ + kind: new EntityKindFilter('template'), + }); + }); }); diff --git a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx index ed54f1fa84..27184bafef 100644 --- a/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx +++ b/plugins/catalog/src/components/CatalogKindHeader/CatalogKindHeader.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import React, { useEffect, useState } from 'react'; +import React, { useEffect, useState, useMemo } from 'react'; import { capitalize, createStyles, @@ -59,12 +59,17 @@ export function CatalogKindHeader(props: CatalogKindHeaderProps) { .getEntityFacets({ facets: ['kind'] }) .then(response => response.facets.kind?.map(f => f.value).sort() || []); }); - const { updateFilters, queryParameters } = useEntityList(); + const { + updateFilters, + queryParameters: { kind: kindParameter }, + } = useEntityList(); + const queryParamKind = useMemo( + () => [kindParameter].flat()[0], + [kindParameter], + ); const [selectedKind, setSelectedKind] = useState( - ([queryParameters.kind].flat()[0] ?? initialFilter).toLocaleLowerCase( - 'en-US', - ), + queryParamKind ?? initialFilter, ); useEffect(() => { @@ -73,6 +78,14 @@ export function CatalogKindHeader(props: CatalogKindHeaderProps) { }); }, [selectedKind, updateFilters]); + // Set selected Kind on query parameter updates; this happens at initial page load and from + // external updates to the page location. + useEffect(() => { + if (queryParamKind) { + setSelectedKind(queryParamKind); + } + }, [queryParamKind]); + // Before allKinds is loaded, or when a kind is entered manually in the URL, selectedKind may not // be present in allKinds. It should still be shown in the dropdown, but may not have the nice // enforced casing from the catalog-backend. This makes a key/value record for the Select options,