mirror of
https://github.com/datahub-project/datahub.git
synced 2025-11-14 02:11:49 +00:00
193 lines
5.7 KiB
TypeScript
193 lines
5.7 KiB
TypeScript
import DeleteOutlinedIcon from '@mui/icons-material/DeleteOutlined';
|
|
import EditOutlinedIcon from '@mui/icons-material/EditOutlined';
|
|
import { Modal, Typography, message } from 'antd';
|
|
import React, { useState } from 'react';
|
|
import styled from 'styled-components';
|
|
import MarkdownViewer from '@src/app/entity/shared/components/legacy/MarkdownViewer';
|
|
import { useDeleteQueryMutation } from '../../../../../../graphql/query.generated';
|
|
import { CorpUser, EntityType } from '../../../../../../types.generated';
|
|
import { useEntityRegistryV2 } from '../../../../../useEntityRegistry';
|
|
import ActorAvatar from '../../../ActorAvatar';
|
|
import { ActionButton } from '../../../containers/profile/sidebar/SectionActionButton';
|
|
import QueryBuilderModal from './QueryBuilderModal';
|
|
import { Query } from './types';
|
|
|
|
/*
|
|
* Description Column
|
|
*/
|
|
|
|
const StyledLink = styled(Typography.Link)`
|
|
display: block;
|
|
`;
|
|
|
|
const TruncatedTextWrapper = styled.div`
|
|
display: inline;
|
|
`;
|
|
|
|
const MAX_DESCRIPTION_LENGTH = 50;
|
|
|
|
interface DescriptionProps {
|
|
description?: string;
|
|
}
|
|
|
|
export const QueryDescription = ({ description }: DescriptionProps) => {
|
|
const [isTruncated, setIsTruncated] = useState(description && description.length > MAX_DESCRIPTION_LENGTH);
|
|
|
|
if (!description) return null;
|
|
|
|
const truncatedDescription = description.slice(0, MAX_DESCRIPTION_LENGTH);
|
|
|
|
return (
|
|
<div>
|
|
{isTruncated && (
|
|
<>
|
|
<TruncatedTextWrapper>
|
|
<MarkdownViewer source={`${truncatedDescription}...`} />
|
|
</TruncatedTextWrapper>
|
|
<StyledLink onClick={() => setIsTruncated(false)}>Read more</StyledLink>
|
|
</>
|
|
)}
|
|
{!isTruncated && (
|
|
<>
|
|
<MarkdownViewer source={description} ignoreLimit />
|
|
{description.length > MAX_DESCRIPTION_LENGTH && (
|
|
<StyledLink onClick={() => setIsTruncated(true)}>Read less</StyledLink>
|
|
)}
|
|
</>
|
|
)}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/*
|
|
* Created By Column
|
|
*/
|
|
|
|
const INGESTION_URN = 'urn:li:corpuser:_ingestion';
|
|
|
|
interface CreatedByProps {
|
|
createdBy?: CorpUser;
|
|
}
|
|
|
|
export const QueryCreatedBy = ({ createdBy }: CreatedByProps) => {
|
|
const entityRegistry = useEntityRegistryV2();
|
|
|
|
if (!createdBy || createdBy.urn === INGESTION_URN) return null;
|
|
|
|
const userName = entityRegistry.getDisplayName(EntityType.CorpUser, createdBy);
|
|
|
|
return (
|
|
<div>
|
|
<ActorAvatar
|
|
size={26}
|
|
name={userName}
|
|
url={`/${entityRegistry.getPathName(EntityType.CorpUser)}/${createdBy.urn}`}
|
|
photoUrl={
|
|
createdBy?.editableProperties?.pictureLink || createdBy?.editableInfo?.pictureLink || undefined
|
|
}
|
|
/>
|
|
</div>
|
|
);
|
|
};
|
|
|
|
/*
|
|
* Edit/Delete Column
|
|
*/
|
|
|
|
const ButtonsWrapper = styled.span<{ $isHidden: boolean }>`
|
|
display: flex;
|
|
gap: 8px;
|
|
align-items: center;
|
|
justify-content: center;
|
|
${(props) => props.$isHidden && `visibility: hidden;`}
|
|
`;
|
|
|
|
interface EditDeleteProps {
|
|
query: Query;
|
|
hoveredQueryUrn: string | null;
|
|
onEdited?: (query) => void;
|
|
onDeleted?: (query) => void;
|
|
}
|
|
|
|
export const EditDeleteColumn = ({ query, hoveredQueryUrn, onEdited, onDeleted }: EditDeleteProps) => {
|
|
const [editingQuery, setEditingQuery] = useState<Query | null>(null);
|
|
const [deleteQueryMutation] = useDeleteQueryMutation();
|
|
const urn = query.urn as string;
|
|
|
|
const deleteQuery = () => {
|
|
deleteQueryMutation({ variables: { urn } })
|
|
.then(({ errors }) => {
|
|
if (!errors) {
|
|
message.success({
|
|
content: `Deleted Query!`,
|
|
duration: 3,
|
|
});
|
|
onDeleted?.(query);
|
|
}
|
|
})
|
|
.catch(() => {
|
|
message.destroy();
|
|
message.error({ content: 'Failed to delete Query! An unexpected error occurred' });
|
|
});
|
|
};
|
|
|
|
const confirmDeleteQuery = () => {
|
|
Modal.confirm({
|
|
title: `Delete Query`,
|
|
content: `Are you sure you want to delete this query?`,
|
|
onOk() {
|
|
deleteQuery();
|
|
},
|
|
onCancel() {},
|
|
okText: 'Yes',
|
|
maskClosable: true,
|
|
closable: true,
|
|
});
|
|
};
|
|
|
|
const onEditSubmitted = (newQuery) => {
|
|
setEditingQuery(null);
|
|
onEdited?.(newQuery);
|
|
};
|
|
|
|
return (
|
|
<>
|
|
<ButtonsWrapper $isHidden={hoveredQueryUrn !== query.urn}>
|
|
<ActionButton privilege onClick={() => setEditingQuery(query)} data-testid="edit-query">
|
|
<EditOutlinedIcon />
|
|
</ActionButton>
|
|
<ActionButton privilege onClick={confirmDeleteQuery} data-testid="delete-query">
|
|
<DeleteOutlinedIcon />
|
|
</ActionButton>
|
|
</ButtonsWrapper>
|
|
{editingQuery && (
|
|
<QueryBuilderModal
|
|
initialState={{
|
|
urn: editingQuery.urn as string,
|
|
title: editingQuery.title,
|
|
description: editingQuery.description,
|
|
query: editingQuery.query,
|
|
}}
|
|
onSubmit={onEditSubmitted}
|
|
onClose={() => setEditingQuery(null)}
|
|
/>
|
|
)}
|
|
</>
|
|
);
|
|
};
|
|
|
|
interface ColumnProps {
|
|
query: Query;
|
|
}
|
|
|
|
const ColumnsWrapper = styled.div`
|
|
text-align: right;
|
|
`;
|
|
|
|
/*
|
|
* Columns Column
|
|
*/
|
|
export const ColumnsColumn = ({ query }: ColumnProps) => {
|
|
return <ColumnsWrapper>{query.columns?.length ?? 0}</ColumnsWrapper>;
|
|
};
|