address review comments
Signed-off-by: Brian Fletcher <brian@roadie.io>
This commit is contained in:
+11
-6
@@ -13,9 +13,10 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Button, Tooltip } from '@material-ui/core';
|
||||
import { IconButton } from '@material-ui/core';
|
||||
import EmailIcon from '@material-ui/icons/Email';
|
||||
import React from 'react';
|
||||
import { Link } from '@backstage/core-components';
|
||||
|
||||
/**
|
||||
* Email Card action link
|
||||
@@ -24,10 +25,14 @@ import React from 'react';
|
||||
*/
|
||||
export const EmailCardAction = ({ email }: { email: string }) => {
|
||||
return (
|
||||
<Tooltip title={`Email ${email}`}>
|
||||
<Button target="_blank" href={`mailto:${email}`} size="small">
|
||||
<EmailIcon color="action" />
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<IconButton
|
||||
component={Link}
|
||||
aria-label="Email"
|
||||
title={`Email ${email}`}
|
||||
to={`mailto:${email}`}
|
||||
target="_blank"
|
||||
>
|
||||
<EmailIcon />
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
+13
-15
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { entityRouteRef } from '../../../routes';
|
||||
import { Tooltip } from '@material-ui/core';
|
||||
import { IconButton } from '@material-ui/core';
|
||||
import InfoIcon from '@material-ui/icons/Info';
|
||||
import React from 'react';
|
||||
import { useRouteRef } from '@backstage/core-plugin-api';
|
||||
@@ -30,19 +30,17 @@ export const EntityCardActions = ({ entity }: { entity: Entity }) => {
|
||||
const entityRoute = useRouteRef(entityRouteRef);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Tooltip title="Show details">
|
||||
<Link
|
||||
component="button"
|
||||
to={entityRoute({
|
||||
name: entity.metadata.name,
|
||||
namespace: entity.metadata.namespace || 'default',
|
||||
kind: entity.kind.toLocaleLowerCase('en-US'),
|
||||
})}
|
||||
>
|
||||
<InfoIcon color="action" />
|
||||
</Link>
|
||||
</Tooltip>
|
||||
</>
|
||||
<IconButton
|
||||
component={Link}
|
||||
aria-label="Show"
|
||||
title="Show details"
|
||||
to={entityRoute({
|
||||
name: entity.metadata.name,
|
||||
namespace: entity.metadata.namespace || 'default',
|
||||
kind: entity.kind.toLocaleLowerCase('en-US'),
|
||||
})}
|
||||
>
|
||||
<InfoIcon />
|
||||
</IconButton>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
/*
|
||||
* Copyright 2022 The Backstage Authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import { Card, CardContent } from '@material-ui/core';
|
||||
import { Alert } from '@material-ui/lab';
|
||||
import React from 'react';
|
||||
|
||||
/**
|
||||
* Entity not found card
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
export const EntityNotFoundCard = ({
|
||||
entityRef,
|
||||
error,
|
||||
}: {
|
||||
entityRef: string;
|
||||
error?: Error;
|
||||
}) => {
|
||||
return (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Alert severity="warning">
|
||||
{entityRef} was not found {error?.message}
|
||||
</Alert>
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
};
|
||||
+59
-1
@@ -22,9 +22,15 @@ import {
|
||||
import Button from '@material-ui/core/Button';
|
||||
import { wrapInTestApp, TestApiProvider } from '@backstage/test-utils';
|
||||
import { catalogApiRef } from '../../api';
|
||||
import { CompoundEntityRef } from '@backstage/catalog-model';
|
||||
import {
|
||||
CompoundEntityRef,
|
||||
parseEntityRef,
|
||||
stringifyEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { entityRouteRef } from '../../routes';
|
||||
import { CatalogApi } from '@backstage/catalog-client';
|
||||
import { Table, TableColumn } from '@backstage/core-components';
|
||||
import { EntityRefLink } from '../EntityRefLink';
|
||||
|
||||
const mockCatalogApi = {
|
||||
getEntityByRef: async (entityRef: CompoundEntityRef) => {
|
||||
@@ -137,3 +143,55 @@ export const SlowCatalogItem = (args: EntityPeekAheadPopoverProps) => (
|
||||
SlowCatalogItem.args = {
|
||||
entityRef: 'component:default/slow.catalog.item',
|
||||
};
|
||||
|
||||
const columns: TableColumn<CompoundEntityRef>[] = [
|
||||
{
|
||||
title: 'entity',
|
||||
render: entityRef => {
|
||||
return (
|
||||
<EntityPeekAheadPopover entityRef={stringifyEntityRef(entityRef)}>
|
||||
<EntityRefLink entityRef={entityRef} />
|
||||
</EntityPeekAheadPopover>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'owner',
|
||||
render: () => {
|
||||
return (
|
||||
<EntityPeekAheadPopover entityRef="user:default/fname.lname">
|
||||
<EntityRefLink
|
||||
entityRef={parseEntityRef('user:default/fname.lname')}
|
||||
/>
|
||||
</EntityPeekAheadPopover>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
title: 'name',
|
||||
render: entityRef => stringifyEntityRef(entityRef),
|
||||
},
|
||||
];
|
||||
export const TableOfItems = (args: { data: CompoundEntityRef[] }) => (
|
||||
<Table columns={columns} data={args.data} />
|
||||
);
|
||||
|
||||
TableOfItems.args = {
|
||||
data: [
|
||||
{
|
||||
name: 'playback',
|
||||
kind: 'component',
|
||||
namespace: 'default',
|
||||
},
|
||||
{
|
||||
name: 'playback',
|
||||
kind: 'component',
|
||||
namespace: 'default',
|
||||
},
|
||||
{
|
||||
name: 'playback',
|
||||
kind: 'component',
|
||||
namespace: 'default',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
+53
-52
@@ -38,13 +38,12 @@ import {
|
||||
isUserEntity,
|
||||
parseEntityRef,
|
||||
} from '@backstage/catalog-model';
|
||||
import { Progress } from '@backstage/core-components';
|
||||
import { Progress, ResponseErrorPanel } from '@backstage/core-components';
|
||||
import {
|
||||
EntityCardActions,
|
||||
UserCardActions,
|
||||
GroupCardActions,
|
||||
} from './CardActionComponents';
|
||||
import { EntityNotFoundCard } from './EntityNotFoundCard';
|
||||
import { debounce } from 'lodash';
|
||||
|
||||
/**
|
||||
@@ -126,11 +125,7 @@ export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => {
|
||||
|
||||
return (
|
||||
<>
|
||||
{' '}
|
||||
<span
|
||||
onMouseEnter={debouncedHandleMouseEnter}
|
||||
onMouseLeave={handleOnMouseLeave}
|
||||
>
|
||||
<span onMouseEnter={debouncedHandleMouseEnter}>
|
||||
<span data-testid="trigger" {...bindHover(popupState)}>
|
||||
{children}
|
||||
</span>
|
||||
@@ -149,56 +144,62 @@ export const EntityPeekAheadPopover = (props: EntityPeekAheadPopoverProps) => {
|
||||
vertical: 'top',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
onMouseLeave={handleOnMouseLeave}
|
||||
>
|
||||
<>
|
||||
{loading && <Progress />}
|
||||
{!entity && !loading && (
|
||||
<EntityNotFoundCard entityRef={entityRef} error={error} />
|
||||
)}
|
||||
{entity && (
|
||||
<Card>
|
||||
<CardContent>
|
||||
<Typography color="textSecondary">
|
||||
{compoundEntityRef.namespace}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="div">
|
||||
{compoundEntityRef.name}
|
||||
</Typography>
|
||||
<Typography color="textSecondary">{entity.kind}</Typography>
|
||||
<Typography
|
||||
className={classes.descriptionTypography}
|
||||
paragraph
|
||||
>
|
||||
{entity.metadata.description}
|
||||
</Typography>
|
||||
<Typography>{entity.spec?.type}</Typography>
|
||||
<Box marginTop="0.5em">
|
||||
{(entity.metadata.tags || [])
|
||||
.slice(0, maxTagChips)
|
||||
.map(tag => {
|
||||
return <Chip key={tag} size="small" label={tag} />;
|
||||
})}
|
||||
{entity.metadata.tags?.length &&
|
||||
entity.metadata.tags?.length > maxTagChips && (
|
||||
<Tooltip title="Drill into the entity to see all of the tags.">
|
||||
<Chip key="other-tags" size="small" label="..." />
|
||||
</Tooltip>
|
||||
)}
|
||||
</Box>
|
||||
</CardContent>
|
||||
<CardActions>
|
||||
{error && <ResponseErrorPanel error={error} />}
|
||||
<Card>
|
||||
{loading && <Progress />}
|
||||
|
||||
<CardContent>
|
||||
{entity && (
|
||||
<>
|
||||
{isUserEntity(entity) && (
|
||||
<UserCardActions entity={entity} />
|
||||
)}
|
||||
{isGroupEntity(entity) && (
|
||||
<GroupCardActions entity={entity} />
|
||||
)}
|
||||
<EntityCardActions entity={entity} />
|
||||
<Typography color="textSecondary">
|
||||
{compoundEntityRef.namespace}
|
||||
</Typography>
|
||||
<Typography variant="h5" component="div">
|
||||
{compoundEntityRef.name}
|
||||
</Typography>
|
||||
<Typography color="textSecondary">{entity.kind}</Typography>
|
||||
<Typography
|
||||
className={classes.descriptionTypography}
|
||||
paragraph
|
||||
>
|
||||
{entity.metadata.description}
|
||||
</Typography>
|
||||
<Typography>{entity.spec?.type}</Typography>
|
||||
<Box marginTop="0.5em">
|
||||
{(entity.metadata.tags || [])
|
||||
.slice(0, maxTagChips)
|
||||
.map(tag => {
|
||||
return <Chip key={tag} size="small" label={tag} />;
|
||||
})}
|
||||
{entity.metadata.tags?.length &&
|
||||
entity.metadata.tags?.length > maxTagChips && (
|
||||
<Tooltip title="Drill into the entity to see all of the tags.">
|
||||
<Chip key="other-tags" size="small" label="..." />
|
||||
</Tooltip>
|
||||
)}
|
||||
</Box>
|
||||
</>
|
||||
)}
|
||||
</CardContent>
|
||||
{!error && (
|
||||
<CardActions>
|
||||
{entity && (
|
||||
<>
|
||||
{isUserEntity(entity) && (
|
||||
<UserCardActions entity={entity} />
|
||||
)}
|
||||
{isGroupEntity(entity) && (
|
||||
<GroupCardActions entity={entity} />
|
||||
)}
|
||||
<EntityCardActions entity={entity} />
|
||||
</>
|
||||
)}
|
||||
</CardActions>
|
||||
</Card>
|
||||
)}
|
||||
)}
|
||||
</Card>
|
||||
</>
|
||||
</HoverPopover>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user