feat(ui): Display 'View in Github' if externalUrl is link to GitHub (#6253)

This commit is contained in:
Chris Collins 2022-10-24 00:29:35 -04:00 committed by GitHub
parent f1aeafa462
commit a28fc1ede8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
19 changed files with 94 additions and 56 deletions

View File

@ -68,6 +68,7 @@ export const ChartPreview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Chart, urn)} url={entityRegistry.getEntityUrl(EntityType.Chart, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
type="Chart" type="Chart"
typeIcon={entityRegistry.getIcon(EntityType.Chart, 14, IconStyleType.ACCENT)} typeIcon={entityRegistry.getIcon(EntityType.Chart, 14, IconStyleType.ACCENT)}

View File

@ -67,6 +67,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Container, urn)} url={entityRegistry.getEntityUrl(EntityType.Container, urn)}
name={name || ''} name={name || ''}
urn={urn}
platform={platformName} platform={platformName}
platformInstanceId={platformInstanceId} platformInstanceId={platformInstanceId}
description={description || ''} description={description || ''}

View File

@ -72,6 +72,7 @@ export const DashboardPreview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Dashboard, urn)} url={entityRegistry.getEntityUrl(EntityType.Dashboard, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
type={capitalizeFirstLetterOnly(subtype) || 'Dashboard'} type={capitalizeFirstLetterOnly(subtype) || 'Dashboard'}
typeIcon={entityRegistry.getIcon(EntityType.Dashboard, 14, IconStyleType.ACCENT)} typeIcon={entityRegistry.getIcon(EntityType.Dashboard, 14, IconStyleType.ACCENT)}

View File

@ -49,6 +49,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.DataFlow, urn)} url={entityRegistry.getEntityUrl(EntityType.DataFlow, urn)}
name={name} name={name}
urn={urn}
description={description || ''} description={description || ''}
platformInstanceId={platformInstanceId} platformInstanceId={platformInstanceId}
type="Data Pipeline" type="Data Pipeline"

View File

@ -52,6 +52,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.DataJob, urn)} url={entityRegistry.getEntityUrl(EntityType.DataJob, urn)}
name={name} name={name}
urn={urn}
description={description || ''} description={description || ''}
type="Data Task" type="Data Task"
typeIcon={entityRegistry.getIcon(EntityType.DataJob, 14, IconStyleType.ACCENT)} typeIcon={entityRegistry.getIcon(EntityType.DataJob, 14, IconStyleType.ACCENT)}

View File

@ -74,6 +74,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Dataset, urn)} url={entityRegistry.getEntityUrl(EntityType.Dataset, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
type={capitalizeFirstLetterOnly(subtype) || 'Dataset'} type={capitalizeFirstLetterOnly(subtype) || 'Dataset'}
logoUrl={platformLogo || ''} logoUrl={platformLogo || ''}

View File

@ -26,6 +26,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Domain, urn)} url={entityRegistry.getEntityUrl(EntityType.Domain, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
type="Domain" type="Domain"
typeIcon={entityRegistry.getIcon(EntityType.Domain, 14, IconStyleType.ACCENT)} typeIcon={entityRegistry.getIcon(EntityType.Domain, 14, IconStyleType.ACCENT)}

View File

@ -22,6 +22,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.GlossaryNode, urn)} url={entityRegistry.getEntityUrl(EntityType.GlossaryNode, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
owners={owners} owners={owners}
logoComponent={<FolderOutlined style={{ fontSize: '20px' }} />} logoComponent={<FolderOutlined style={{ fontSize: '20px' }} />}

View File

@ -28,6 +28,7 @@ export const Preview = ({
previewType={previewType} previewType={previewType}
url={entityRegistry.getEntityUrl(EntityType.GlossaryTerm, urn)} url={entityRegistry.getEntityUrl(EntityType.GlossaryTerm, urn)}
name={name || ''} name={name || ''}
urn={urn}
description={description || ''} description={description || ''}
owners={owners} owners={owners}
logoComponent={<BookOutlined style={{ fontSize: '20px' }} />} logoComponent={<BookOutlined style={{ fontSize: '20px' }} />}

View File

@ -27,6 +27,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Mlfeature, urn)} url={entityRegistry.getEntityUrl(EntityType.Mlfeature, urn)}
name={name} name={name}
urn={urn}
platformInstanceId={platformInstanceId} platformInstanceId={platformInstanceId}
description={description || ''} description={description || ''}
platform={capitalizeFirstLetterOnly(platform?.properties?.displayName) || featureNamespace} platform={capitalizeFirstLetterOnly(platform?.properties?.displayName) || featureNamespace}

View File

@ -26,6 +26,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.MlfeatureTable, urn)} url={entityRegistry.getEntityUrl(EntityType.MlfeatureTable, urn)}
name={name} name={name}
urn={urn}
description={description || ''} description={description || ''}
type={entityRegistry.getEntityName(EntityType.MlfeatureTable)} type={entityRegistry.getEntityName(EntityType.MlfeatureTable)}
typeIcon={entityRegistry.getIcon(EntityType.MlfeatureTable, 14, IconStyleType.ACCENT)} typeIcon={entityRegistry.getIcon(EntityType.MlfeatureTable, 14, IconStyleType.ACCENT)}

View File

@ -13,6 +13,7 @@ export const Preview = ({ model }: { model: MlModel }): JSX.Element => {
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.Mlmodel, model.urn)} url={entityRegistry.getEntityUrl(EntityType.Mlmodel, model.urn)}
name={model.name || ''} name={model.name || ''}
urn={model.urn}
description={model.description || ''} description={model.description || ''}
platformInstanceId={model.dataPlatformInstance?.instanceId} platformInstanceId={model.dataPlatformInstance?.instanceId}
type={entityRegistry.getEntityName(EntityType.Mlmodel)} type={entityRegistry.getEntityName(EntityType.Mlmodel)}

View File

@ -12,6 +12,7 @@ export const Preview = ({ group }: { group: MlModelGroup }): JSX.Element => {
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.MlmodelGroup, group.urn)} url={entityRegistry.getEntityUrl(EntityType.MlmodelGroup, group.urn)}
name={group?.name || ''} name={group?.name || ''}
urn={group.urn}
platformInstanceId={group.dataPlatformInstance?.instanceId} platformInstanceId={group.dataPlatformInstance?.instanceId}
description={group?.description || ''} description={group?.description || ''}
type="MLModel Group" type="MLModel Group"

View File

@ -27,6 +27,7 @@ export const Preview = ({
<DefaultPreviewCard <DefaultPreviewCard
url={entityRegistry.getEntityUrl(EntityType.MlprimaryKey, urn)} url={entityRegistry.getEntityUrl(EntityType.MlprimaryKey, urn)}
name={name} name={name}
urn={urn}
description={description || ''} description={description || ''}
platform={capitalizeFirstLetterOnly(platform?.properties?.displayName) || featureNamespace} platform={capitalizeFirstLetterOnly(platform?.properties?.displayName) || featureNamespace}
logoUrl={platform?.properties?.logoUrl || ''} logoUrl={platform?.properties?.logoUrl || ''}

View File

@ -0,0 +1,61 @@
import { ArrowRightOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import React from 'react';
import styled from 'styled-components/macro';
import { EntityType } from '../../../types.generated';
import analytics, { EventType, EntityActionType } from '../../analytics';
const GITHUB_LINK = 'github.com';
const GITHUB = 'GitHub';
const ExternalUrlWrapper = styled.span`
font-size: 12px;
`;
const StyledButton = styled(Button)`
> :hover {
text-decoration: underline;
}
&&& {
padding-bottom: 0px;
}
padding-left: 12px;
padding-right: 12px;
`;
interface Props {
externalUrl: string;
platformName?: string;
entityUrn: string;
entityType?: string;
}
export default function ExternalUrlButton({ externalUrl, platformName, entityType, entityUrn }: Props) {
function sendAnalytics() {
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.ClickExternalUrl,
entityType: entityType as EntityType,
entityUrn,
});
}
let displayedName = platformName;
if (externalUrl.toLocaleLowerCase().includes(GITHUB_LINK)) {
displayedName = GITHUB;
}
return (
<ExternalUrlWrapper>
<StyledButton
type="link"
href={externalUrl}
target="_blank"
rel="noreferrer noopener"
onClick={sendAnalytics}
>
View in {displayedName} <ArrowRightOutlined style={{ fontSize: 12 }} />
</StyledButton>
</ExternalUrlWrapper>
);
}

View File

@ -1,10 +1,7 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { ArrowRightOutlined } from '@ant-design/icons';
import { Button } from 'antd';
import styled from 'styled-components/macro'; import styled from 'styled-components/macro';
import { capitalizeFirstLetterOnly } from '../../../../../shared/textUtil'; import { capitalizeFirstLetterOnly } from '../../../../../shared/textUtil';
import { useEntityData, useRefetch } from '../../../EntityContext'; import { useEntityData, useRefetch } from '../../../EntityContext';
import analytics, { EventType, EntityActionType } from '../../../../../analytics';
import { EntityHealthStatus } from './EntityHealthStatus'; import { EntityHealthStatus } from './EntityHealthStatus';
import EntityDropdown, { EntityMenuItems } from '../../../EntityDropdown/EntityDropdown'; import EntityDropdown, { EntityMenuItems } from '../../../EntityDropdown/EntityDropdown';
import PlatformContent from './PlatformContent'; import PlatformContent from './PlatformContent';
@ -18,6 +15,7 @@ import { DeprecationPill } from '../../../components/styled/DeprecationPill';
import CompactContext from '../../../../../shared/CompactContext'; import CompactContext from '../../../../../shared/CompactContext';
import { EntitySubHeaderSection } from '../../../types'; import { EntitySubHeaderSection } from '../../../types';
import EntityActions, { EntityActionItem } from '../../../entity/EntityActions'; import EntityActions, { EntityActionItem } from '../../../entity/EntityActions';
import ExternalUrlButton from '../../../ExternalUrlButton';
const TitleWrapper = styled.div` const TitleWrapper = styled.div`
display: flex; display: flex;
@ -57,18 +55,6 @@ const TopButtonsWrapper = styled.div`
margin-bottom: 8px; margin-bottom: 8px;
`; `;
const ExternalUrlContainer = styled.span`
font-size: 14px;
`;
const ExternalUrlButton = styled(Button)`
> :hover {
text-decoration: underline;
}
padding-left: 12px;
padding-right: 12px;
`;
export function getCanEditName(entityType: EntityType, privileges?: PlatformPrivileges) { export function getCanEditName(entityType: EntityType, privileges?: PlatformPrivileges) {
switch (entityType) { switch (entityType) {
case EntityType.GlossaryTerm: case EntityType.GlossaryTerm:
@ -106,15 +92,6 @@ export const EntityHeader = ({
const entityCount = entityData?.entityCount; const entityCount = entityData?.entityCount;
const isCompact = React.useContext(CompactContext); const isCompact = React.useContext(CompactContext);
const sendAnalytics = () => {
analytics.event({
type: EventType.EntityActionEvent,
actionType: EntityActionType.ClickExternalUrl,
entityType,
entityUrn: urn,
});
};
const canEditName = isNameEditable && getCanEditName(entityType, me?.platformPrivileges as PlatformPrivileges); const canEditName = isNameEditable && getCanEditName(entityType, me?.platformPrivileges as PlatformPrivileges);
return ( return (
@ -146,16 +123,12 @@ export const EntityHeader = ({
<SideHeaderContent> <SideHeaderContent>
<TopButtonsWrapper> <TopButtonsWrapper>
{externalUrl && ( {externalUrl && (
<ExternalUrlContainer> <ExternalUrlButton
<ExternalUrlButton externalUrl={externalUrl}
type="link" entityUrn={urn}
href={externalUrl} platformName={platformName}
target="_blank" entityType={entityType}
onClick={sendAnalytics} />
>
View in {platformName} <ArrowRightOutlined style={{ fontSize: 12 }} />
</ExternalUrlButton>
</ExternalUrlContainer>
)} )}
{headerActionItems && ( {headerActionItems && (
<EntityActions urn={urn} actionItems={headerActionItems} refetchForEntity={refetch} /> <EntityActions urn={urn} actionItems={headerActionItems} refetchForEntity={refetch} />

View File

@ -57,6 +57,7 @@ export class TagEntity implements Entity<Tag> {
<DefaultPreviewCard <DefaultPreviewCard
description={data.description || ''} description={data.description || ''}
name={data.name} name={data.name}
urn={data.urn}
url={`/${this.getPathName()}/${urlEncodeUrn(data.urn)}`} url={`/${this.getPathName()}/${urlEncodeUrn(data.urn)}`}
logoComponent={<PreviewTagIcon />} logoComponent={<PreviewTagIcon />}
type="Tag" type="Tag"

View File

@ -1,8 +1,7 @@
import React, { ReactNode, useState } from 'react'; import React, { ReactNode, useState } from 'react';
import { Button, Divider, Tooltip, Typography } from 'antd'; import { Divider, Tooltip, Typography } from 'antd';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { ArrowRightOutlined } from '@ant-design/icons';
import { import {
GlobalTags, GlobalTags,
@ -28,6 +27,7 @@ import EntityCount from '../entity/shared/containers/profile/header/EntityCount'
import { ExpandedActorGroup } from '../entity/shared/components/styled/ExpandedActorGroup'; import { ExpandedActorGroup } from '../entity/shared/components/styled/ExpandedActorGroup';
import { DeprecationPill } from '../entity/shared/components/styled/DeprecationPill'; import { DeprecationPill } from '../entity/shared/components/styled/DeprecationPill';
import { PreviewType } from '../entity/Entity'; import { PreviewType } from '../entity/Entity';
import ExternalUrlButton from '../entity/shared/ExternalUrlButton';
const PreviewContainer = styled.div` const PreviewContainer = styled.div`
display: flex; display: flex;
@ -129,21 +129,6 @@ const InsightIconContainer = styled.span`
margin-right: 4px; margin-right: 4px;
`; `;
const ExternalUrlContainer = styled.span`
font-size: 12px;
`;
const ExternalUrlButton = styled(Button)`
> :hover {
text-decoration: underline;
}
&&& {
padding-bottom: 0px;
}
padding-left: 12px;
padding-right: 12px;
`;
const UserListContainer = styled.div` const UserListContainer = styled.div`
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -164,6 +149,7 @@ const UserListTitle = styled(Typography.Text)`
interface Props { interface Props {
name: string; name: string;
urn: string;
logoUrl?: string; logoUrl?: string;
logoComponent?: JSX.Element; logoComponent?: JSX.Element;
url: string; url: string;
@ -200,6 +186,7 @@ interface Props {
export default function DefaultPreviewCard({ export default function DefaultPreviewCard({
name, name,
urn,
logoUrl, logoUrl,
logoComponent, logoComponent,
url, url,
@ -292,11 +279,12 @@ export default function DefaultPreviewCard({
<DeprecationPill deprecation={deprecation} urn="" showUndeprecate={false} preview /> <DeprecationPill deprecation={deprecation} urn="" showUndeprecate={false} preview />
)} )}
{externalUrl && ( {externalUrl && (
<ExternalUrlContainer> <ExternalUrlButton
<ExternalUrlButton type="link" href={externalUrl} target="_blank"> externalUrl={externalUrl}
View in {platform} <ArrowRightOutlined style={{ fontSize: 12 }} /> platformName={platform}
</ExternalUrlButton> entityUrn={urn}
</ExternalUrlContainer> entityType={type}
/>
)} )}
</EntityTitleContainer> </EntityTitleContainer>

View File

@ -140,6 +140,7 @@ export const EntityNameList = ({
)} )}
<DefaultPreviewCard <DefaultPreviewCard
name={displayName} name={displayName}
urn={entity.urn}
logoUrl={platformLogoUrl || undefined} logoUrl={platformLogoUrl || undefined}
logoComponent={fallbackIcon} logoComponent={fallbackIcon}
url={url} url={url}