diff --git a/.changeset/quick-cougars-fry.md b/.changeset/quick-cougars-fry.md new file mode 100644 index 0000000000..6ae8b66eda --- /dev/null +++ b/.changeset/quick-cougars-fry.md @@ -0,0 +1,9 @@ +--- +'@backstage/plugin-home': patch +--- + +Improve Starred Entities UI to reduce whitespace and provide more context on the entities: + +- Use the Entity Presentation API (via ``) to display the entity's name +- Component's `kind` and `spec.type` are displayed as a secondary text +- List items are condensed to reduce unnecessary spacing diff --git a/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx b/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx index 8081e71407..524a7d7d53 100644 --- a/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx +++ b/plugins/home/src/components/StarredEntityListItem/StarredEntityListItem.tsx @@ -13,8 +13,11 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; -import { entityRouteParams } from '@backstage/plugin-catalog-react'; +import { Entity } from '@backstage/catalog-model'; +import { + EntityDisplayName, + entityRouteParams, +} from '@backstage/plugin-catalog-react'; import ListItem from '@material-ui/core/ListItem'; import ListItemIcon from '@material-ui/core/ListItemIcon'; import ListItemText from '@material-ui/core/ListItemText'; @@ -23,21 +26,59 @@ import { Link } from 'react-router-dom'; import { entityRouteRef } from '@backstage/plugin-catalog-react'; import { useRouteRef } from '@backstage/core-plugin-api'; import { FavoriteToggle } from '@backstage/core-components'; +import { makeStyles } from '@material-ui/core/styles'; type EntityListItemProps = { entity: Entity; onToggleStarredEntity: (entity: Entity) => void; + showKind?: boolean; }; +const useStyles = makeStyles(theme => ({ + listItem: { + paddingBottom: theme.spacing(0), + paddingTop: theme.spacing(0), + }, + secondary: { + textTransform: 'uppercase', + }, +})); + export const StarredEntityListItem = ({ entity, onToggleStarredEntity, + showKind, }: EntityListItemProps) => { + const classes = useStyles(); const catalogEntityRoute = useRouteRef(entityRouteRef); + let secondaryText = ''; + if (showKind) { + secondaryText += entity.kind.toLocaleLowerCase('en-US'); + } + if (entity.spec && 'type' in entity.spec) { + if (showKind) { + secondaryText += ' — '; + } + secondaryText += (entity.spec as { type: string }).type.toLocaleLowerCase( + 'en-US', + ); + } + return ( - - + + { + e.preventDefault(); + }} + > onToggleStarredEntity(entity)} /> - - - + } + secondary={secondaryText} + /> ); }; diff --git a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx index d0a6f000df..bc5e3e2923 100644 --- a/plugins/home/src/homePageComponents/StarredEntities/Content.tsx +++ b/plugins/home/src/homePageComponents/StarredEntities/Content.tsx @@ -28,22 +28,38 @@ import Tab from '@material-ui/core/Tab'; import React from 'react'; import useAsync from 'react-use/esm/useAsync'; import { StarredEntityListItem } from '../../components/StarredEntityListItem/StarredEntityListItem'; +import { makeStyles } from '@material-ui/core/styles'; + +const useStyles = makeStyles(theme => ({ + tabs: { + marginBottom: theme.spacing(1), + }, + list: { + paddingTop: 0, + paddingBottom: 0, + }, +})); + +/** + * Props for the StarredEntities component + * + * @public + */ +export type StarredEntitiesProps = { + noStarredEntitiesMessage?: React.ReactNode | undefined; + groupByKind?: boolean; +}; /** * A component to display a list of starred entities for the user. * * @public */ - -export type StarredEntitiesProps = { - noStarredEntitiesMessage?: React.ReactNode | undefined; - groupByKind?: boolean; -}; - export const Content = ({ noStarredEntitiesMessage, groupByKind, }: StarredEntitiesProps) => { + const classes = useStyles(); const catalogApi = useApi(catalogApiRef); const { starredEntities, toggleStarredEntity } = useStarredEntities(); const [activeTab, setActiveTab] = React.useState(0); @@ -57,12 +73,7 @@ export const Content = ({ return ( await catalogApi.getEntitiesByRefs({ entityRefs: [...starredEntities], - fields: [ - 'kind', - 'metadata.namespace', - 'metadata.name', - 'metadata.title', - ], + fields: ['kind', 'metadata.namespace', 'metadata.name', 'spec.type'], }) ).items.filter((e): e is Entity => !!e); }, [catalogApi, starredEntities]); @@ -95,7 +106,7 @@ export const Content = ({ ) : (
{!groupByKind && ( - + {entities.value ?.sort((a, b) => (a.metadata.title ?? a.metadata.name).localeCompare( @@ -107,6 +118,7 @@ export const Content = ({ key={stringifyEntityRef(entity)} entity={entity} onToggleStarredEntity={toggleStarredEntity} + showKind /> ))} @@ -114,6 +126,7 @@ export const Content = ({ {groupByKind && ( setActiveTab(newValue)} variant="scrollable" @@ -129,7 +142,7 @@ export const Content = ({ {groupByKind && groupByKindEntries.map(([kind, entitiesByKind], index) => (