feat(catalog/star): Ability to star items in the catalog table

This commit is contained in:
blam
2020-06-09 15:20:38 +02:00
parent 00d33f93e4
commit 90f253aaf8
3 changed files with 59 additions and 4 deletions
@@ -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
+14 -1
View File
@@ -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();
});
});