feat(catalog/star): Ability to star items in the catalog table
This commit is contained in:
@@ -29,6 +29,8 @@ import {
|
||||
import { rootRoute as scaffolderRootRoute } from '@backstage/plugin-scaffolder';
|
||||
import { Button, makeStyles, Typography, Link } from '@material-ui/core';
|
||||
import GitHub from '@material-ui/icons/GitHub';
|
||||
import StarOutline from '@material-ui/icons/StarBorder';
|
||||
import Star from '@material-ui/icons/Star';
|
||||
import React, { FC, useCallback, useState } from 'react';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import { useAsync } from 'react-use';
|
||||
@@ -60,13 +62,14 @@ const useStyles = makeStyles(theme => ({
|
||||
|
||||
const CatalogPage: FC<{}> = () => {
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const { starredEntities } = useStarredEntities();
|
||||
const { starredEntities, toggleStarredEntity } = useStarredEntities();
|
||||
const [selectedFilter, setSelectedFilter] = useState<CatalogFilterItem>(
|
||||
defaultFilter,
|
||||
);
|
||||
|
||||
const { value, error, loading } = useAsync(
|
||||
() => dataResolvers[selectedFilter.id]({ catalogApi, starredEntities }),
|
||||
[selectedFilter.id],
|
||||
[selectedFilter.id, starredEntities.size],
|
||||
);
|
||||
|
||||
const onFilterSelected = useCallback(
|
||||
@@ -89,6 +92,15 @@ const CatalogPage: FC<{}> = () => {
|
||||
hidden: location ? location?.type !== 'github' : true,
|
||||
};
|
||||
},
|
||||
(rowData: Component) => {
|
||||
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),
|
||||
};
|
||||
},
|
||||
];
|
||||
|
||||
// TODO: replace me with the proper tabs implemntation
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useState, useEffect, useCallback } from 'react';
|
||||
import { useApi, storageApiRef } from '@backstage/core';
|
||||
import { useObservable } from 'react-use';
|
||||
|
||||
@@ -37,7 +37,20 @@ export const useStarredEntities = () => {
|
||||
}
|
||||
}, [observedItems?.newValue]);
|
||||
|
||||
const toggleStarredEntity = useCallback(
|
||||
(entity: string) => {
|
||||
if (starredEntities.has(entity)) {
|
||||
starredEntities.delete(entity);
|
||||
} else {
|
||||
starredEntities.add(entity);
|
||||
}
|
||||
|
||||
settingsStore.set('starredEntities', Array.from(starredEntities));
|
||||
},
|
||||
[starredEntities, settingsStore],
|
||||
);
|
||||
return {
|
||||
starredEntities,
|
||||
toggleStarredEntity,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React from 'react';
|
||||
import { renderHook } from '@testing-library/react-hooks';
|
||||
import { renderHook, act } from '@testing-library/react-hooks';
|
||||
import { useStarredEntities } from './useStarredEntites';
|
||||
import {
|
||||
ApiProvider,
|
||||
@@ -77,4 +77,34 @@ describe('useStarredEntities', () => {
|
||||
expect(result.current.starredEntities.size).toBe(1);
|
||||
expect(result.current.starredEntities.has('something')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should write new entries to the local store when adding a togglging entity', async () => {
|
||||
const store = mockStorage?.forBucket('settings');
|
||||
|
||||
await store?.set('starredEntities', ['something1']);
|
||||
|
||||
const { result } = renderHook(() => useStarredEntities(), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.toggleStarredEntity('something2');
|
||||
});
|
||||
|
||||
expect(result.current.starredEntities.has('something2')).toBeTruthy();
|
||||
expect(result.current.starredEntities.has('something1')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should remove an existing entity when toggling entries', async () => {
|
||||
const store = mockStorage?.forBucket('settings');
|
||||
|
||||
await store?.set('starredEntities', ['something1', 'something2']);
|
||||
|
||||
const { result } = renderHook(() => useStarredEntities(), { wrapper });
|
||||
|
||||
act(() => {
|
||||
result.current.toggleStarredEntity('something2');
|
||||
});
|
||||
|
||||
expect(result.current.starredEntities.has('something2')).toBeFalsy();
|
||||
expect(result.current.starredEntities.has('something1')).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user