diff --git a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx index 2c59b3f319..426b3f8470 100644 --- a/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx +++ b/plugins/catalog/src/components/CatalogPage/CatalogPage.tsx @@ -64,7 +64,11 @@ const useStyles = makeStyles(theme => ({ const CatalogPage: FC<{}> = () => { const catalogApi = useApi(catalogApiRef); - const { starredEntities, toggleStarredEntity } = useStarredEntities(); + const { + starredEntities, + toggleStarredEntity, + isStarredEntity, + } = useStarredEntities(); const [selectedFilter, setSelectedFilter] = useState( defaultFilter, ); @@ -118,12 +122,11 @@ const CatalogPage: FC<{}> = () => { }; }, (rowData: Component) => { + const isStarred = isStarredEntity(rowData); return { - icon: starredEntities.has(rowData.metadata.name) ? Star : StarOutline, - toolTip: `${ - starredEntities.has(rowData.metadata.name) ? 'Unstar' : 'Star' - } ${rowData.metadata.name}`, - onClick: () => toggleStarredEntity(rowData.metadata.name), + icon: isStarred ? Star : StarOutline, + tooltip: isStarred ? 'Remove from favorites' : 'Add to favorites', + onClick: () => toggleStarredEntity(rowData), }; }, ]; diff --git a/plugins/catalog/src/hooks/useStarredEntites.ts b/plugins/catalog/src/hooks/useStarredEntites.ts index 3d1f902583..4c8751d142 100644 --- a/plugins/catalog/src/hooks/useStarredEntites.ts +++ b/plugins/catalog/src/hooks/useStarredEntites.ts @@ -16,14 +16,21 @@ import { useState, useEffect, useCallback } from 'react'; import { useApi, storageApiRef } from '@backstage/core'; import { useObservable } from 'react-use'; +import { Component } from '../data/component'; + +const buildEntityKey = (component: Component) => + `entity:${component.kind}:${component.metadata.namespace ?? 'default'}:${ + component.metadata.name + }`; export const useStarredEntities = () => { const storageApi = useApi(storageApiRef); const settingsStore = storageApi.forBucket('settings'); - const rawStarredItems = settingsStore.get('starredEntities') ?? []; + const rawStarredEntityKeys = + settingsStore.get('starredEntities') ?? []; const [starredEntities, setStarredEntities] = useState( - new Set(rawStarredItems), + new Set(rawStarredEntityKeys), ); const observedItems = useObservable( @@ -38,19 +45,30 @@ export const useStarredEntities = () => { }, [observedItems?.newValue]); const toggleStarredEntity = useCallback( - (entity: string) => { - if (starredEntities.has(entity)) { - starredEntities.delete(entity); + (entity: Component) => { + const entityKey = buildEntityKey(entity); + if (starredEntities.has(entityKey)) { + starredEntities.delete(entityKey); } else { - starredEntities.add(entity); + starredEntities.add(entityKey); } settingsStore.set('starredEntities', Array.from(starredEntities)); }, [starredEntities, settingsStore], ); + + const isStarredEntity = useCallback( + (entity: Component) => { + const entityKey = buildEntityKey(entity); + return starredEntities.has(entityKey); + }, + [starredEntities], + ); + return { starredEntities, toggleStarredEntity, + isStarredEntity, }; }; diff --git a/plugins/catalog/src/hooks/useStarredEntities.test.tsx b/plugins/catalog/src/hooks/useStarredEntities.test.tsx index 8127d71d50..607318b45c 100644 --- a/plugins/catalog/src/hooks/useStarredEntities.test.tsx +++ b/plugins/catalog/src/hooks/useStarredEntities.test.tsx @@ -24,9 +24,18 @@ import { StorageApi, } from '@backstage/core'; import { MockErrorApi } from '@backstage/test-utils'; +import { Component } from '../data/component'; describe('useStarredEntities', () => { let mockStorage: StorageApi | undefined; + const mockEntity: Component = { + description: 'some mock description', + kind: 'Component', + name: 'mock', + metadata: { + name: 'mock', + }, + }; const wrapper: React.FC<{}> = ({ children }) => { return (