2022-08-19 15:58:31 -04:00
|
|
|
import { blue } from '@ant-design/colors';
|
|
|
|
import { CodeOutlined, CopyOutlined, DeleteOutlined } from '@ant-design/icons';
|
|
|
|
import { Button, Image, Tooltip, Typography } from 'antd';
|
|
|
|
import cronstrue from 'cronstrue';
|
|
|
|
import React from 'react';
|
|
|
|
import styled from 'styled-components/macro';
|
|
|
|
import { ANTD_GRAY } from '../../entity/shared/constants';
|
|
|
|
import { capitalizeFirstLetter } from '../../shared/textUtil';
|
2022-09-13 13:27:12 -04:00
|
|
|
import useGetSourceLogoUrl from './builder/useGetSourceLogoUrl';
|
2022-08-19 15:58:31 -04:00
|
|
|
import {
|
|
|
|
getExecutionRequestStatusDisplayColor,
|
|
|
|
getExecutionRequestStatusDisplayText,
|
|
|
|
getExecutionRequestStatusIcon,
|
|
|
|
RUNNING,
|
|
|
|
} from './utils';
|
|
|
|
|
|
|
|
const PreviewImage = styled(Image)`
|
|
|
|
max-height: 28px;
|
|
|
|
width: auto;
|
|
|
|
object-fit: contain;
|
|
|
|
margin: 0px;
|
|
|
|
background-color: transparent;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const StatusContainer = styled.div`
|
|
|
|
display: flex;
|
|
|
|
justify-content: left;
|
|
|
|
align-items: center;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const StatusButton = styled(Button)`
|
|
|
|
padding: 0px;
|
|
|
|
margin: 0px;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const ActionButtonContainer = styled.div`
|
|
|
|
display: flex;
|
|
|
|
justify-content: right;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const TypeWrapper = styled.div`
|
|
|
|
align-items: center;
|
|
|
|
display: flex;
|
|
|
|
`;
|
|
|
|
|
|
|
|
const CliBadge = styled.span`
|
|
|
|
margin-left: 20px;
|
|
|
|
border-radius: 15px;
|
|
|
|
border: 1px solid ${ANTD_GRAY[8]};
|
|
|
|
padding: 1px 4px;
|
|
|
|
font-size: 10px;
|
|
|
|
|
|
|
|
font-size: 8px;
|
|
|
|
font-weight: bold;
|
|
|
|
letter-spacing: 0.5px;
|
|
|
|
border: 1px solid ${blue[6]};
|
|
|
|
color: ${blue[6]};
|
|
|
|
|
|
|
|
svg {
|
|
|
|
display: none;
|
|
|
|
margin-right: 5px;
|
|
|
|
}
|
|
|
|
`;
|
|
|
|
|
|
|
|
export function TypeColumn(type: string, record: any) {
|
2022-09-13 13:27:12 -04:00
|
|
|
const iconUrl = useGetSourceLogoUrl(type);
|
2022-08-19 15:58:31 -04:00
|
|
|
const typeDisplayName = capitalizeFirstLetter(type);
|
|
|
|
|
|
|
|
return (
|
|
|
|
<TypeWrapper>
|
|
|
|
{iconUrl ? (
|
|
|
|
<Tooltip overlay={typeDisplayName}>
|
|
|
|
<PreviewImage preview={false} src={iconUrl} alt={type || ''} />
|
|
|
|
</Tooltip>
|
|
|
|
) : (
|
|
|
|
<Typography.Text strong>{typeDisplayName}</Typography.Text>
|
|
|
|
)}
|
|
|
|
{record.cliIngestion && (
|
|
|
|
<Tooltip title="This source is ingested from the command-line interface (CLI)">
|
|
|
|
<CliBadge>
|
|
|
|
<CodeOutlined />
|
|
|
|
CLI
|
|
|
|
</CliBadge>
|
|
|
|
</Tooltip>
|
|
|
|
)}
|
|
|
|
</TypeWrapper>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
export function LastExecutionColumn(time: any) {
|
|
|
|
const executionDate = time && new Date(time);
|
|
|
|
const localTime = executionDate && `${executionDate.toLocaleDateString()} at ${executionDate.toLocaleTimeString()}`;
|
2022-11-04 14:59:30 -07:00
|
|
|
return <Typography.Text>{localTime || 'None'}</Typography.Text>;
|
2022-08-19 15:58:31 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
export function ScheduleColumn(schedule: any, record: any) {
|
|
|
|
const tooltip = schedule && `Runs ${cronstrue.toString(schedule).toLowerCase()} (${record.timezone})`;
|
|
|
|
return (
|
|
|
|
<Tooltip title={tooltip || 'Not scheduled'}>
|
|
|
|
<Typography.Text code>{schedule || 'None'}</Typography.Text>
|
|
|
|
</Tooltip>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
interface LastStatusProps {
|
|
|
|
status: any;
|
|
|
|
record: any;
|
|
|
|
setFocusExecutionUrn: (urn: string) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function LastStatusColumn({ status, record, setFocusExecutionUrn }: LastStatusProps) {
|
|
|
|
const Icon = getExecutionRequestStatusIcon(status);
|
|
|
|
const text = getExecutionRequestStatusDisplayText(status);
|
|
|
|
const color = getExecutionRequestStatusDisplayColor(status);
|
|
|
|
return (
|
|
|
|
<StatusContainer>
|
2022-11-04 14:59:30 -07:00
|
|
|
{Icon && <Icon style={{ color, fontSize: 14 }} />}
|
2022-08-19 15:58:31 -04:00
|
|
|
<StatusButton type="link" onClick={() => setFocusExecutionUrn(record.lastExecUrn)}>
|
|
|
|
<Typography.Text strong style={{ color, marginLeft: 8 }}>
|
2022-11-04 14:59:30 -07:00
|
|
|
{text || 'Pending...'}
|
2022-08-19 15:58:31 -04:00
|
|
|
</Typography.Text>
|
|
|
|
</StatusButton>
|
|
|
|
</StatusContainer>
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
interface ActionsColumnProps {
|
|
|
|
record: any;
|
|
|
|
setFocusExecutionUrn: (urn: string) => void;
|
|
|
|
onExecute: (urn: string) => void;
|
|
|
|
onEdit: (urn: string) => void;
|
|
|
|
onView: (urn: string) => void;
|
|
|
|
onDelete: (urn: string) => void;
|
|
|
|
}
|
|
|
|
|
|
|
|
export function ActionsColumn({
|
|
|
|
record,
|
|
|
|
onEdit,
|
|
|
|
setFocusExecutionUrn,
|
|
|
|
onView,
|
|
|
|
onExecute,
|
|
|
|
onDelete,
|
|
|
|
}: ActionsColumnProps) {
|
|
|
|
return (
|
|
|
|
<ActionButtonContainer>
|
|
|
|
{navigator.clipboard && (
|
|
|
|
<Tooltip title="Copy Ingestion Source URN">
|
|
|
|
<Button
|
|
|
|
style={{ marginRight: 16 }}
|
|
|
|
icon={<CopyOutlined />}
|
|
|
|
onClick={() => {
|
|
|
|
navigator.clipboard.writeText(record.urn);
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
</Tooltip>
|
|
|
|
)}
|
|
|
|
{!record.cliIngestion && (
|
|
|
|
<Button style={{ marginRight: 16 }} onClick={() => onEdit(record.urn)}>
|
|
|
|
EDIT
|
|
|
|
</Button>
|
|
|
|
)}
|
|
|
|
{record.cliIngestion && (
|
|
|
|
<Button style={{ marginRight: 16 }} onClick={() => onView(record.urn)}>
|
|
|
|
VIEW
|
|
|
|
</Button>
|
|
|
|
)}
|
|
|
|
{record.lastExecStatus !== RUNNING && (
|
|
|
|
<Button
|
|
|
|
disabled={record.cliIngestion}
|
|
|
|
style={{ marginRight: 16 }}
|
|
|
|
onClick={() => onExecute(record.urn)}
|
|
|
|
>
|
|
|
|
RUN
|
|
|
|
</Button>
|
|
|
|
)}
|
|
|
|
{record.lastExecStatus === RUNNING && (
|
|
|
|
<Button style={{ marginRight: 16 }} onClick={() => setFocusExecutionUrn(record.lastExecUrn)}>
|
|
|
|
DETAILS
|
|
|
|
</Button>
|
|
|
|
)}
|
|
|
|
<Button onClick={() => onDelete(record.urn)} type="text" shape="circle" danger>
|
|
|
|
<DeleteOutlined />
|
|
|
|
</Button>
|
|
|
|
</ActionButtonContainer>
|
|
|
|
);
|
|
|
|
}
|