diff --git a/datahub-web-react/src/app/entityV2/shared/EntityDropdown/EntityDropdown.tsx b/datahub-web-react/src/app/entityV2/shared/EntityDropdown/EntityDropdown.tsx index ea49b3902b1e..95ac986b17c2 100644 --- a/datahub-web-react/src/app/entityV2/shared/EntityDropdown/EntityDropdown.tsx +++ b/datahub-web-react/src/app/entityV2/shared/EntityDropdown/EntityDropdown.tsx @@ -1,7 +1,7 @@ -import { Menu } from '@components'; -import MoreVertOutlinedIcon from '@mui/icons-material/MoreVertOutlined'; +import { Menu, toast } from '@components'; import { ClockCounterClockwise } from '@phosphor-icons/react/dist/csr/ClockCounterClockwise'; import { Copy } from '@phosphor-icons/react/dist/csr/Copy'; +import { DotsThreeVertical } from '@phosphor-icons/react/dist/csr/DotsThreeVertical'; import { Envelope } from '@phosphor-icons/react/dist/csr/Envelope'; import { FolderOpen } from '@phosphor-icons/react/dist/csr/FolderOpen'; import { FolderPlus } from '@phosphor-icons/react/dist/csr/FolderPlus'; @@ -15,12 +15,11 @@ import { Plus } from '@phosphor-icons/react/dist/csr/Plus'; import { Share } from '@phosphor-icons/react/dist/csr/Share'; import { Trash } from '@phosphor-icons/react/dist/csr/Trash'; import { Warning } from '@phosphor-icons/react/dist/csr/Warning'; -import { message } from 'antd'; import qs from 'query-string'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; import { Redirect, useHistory } from 'react-router'; -import styled, { useTheme } from 'styled-components'; +import { useTheme } from 'styled-components'; import { EventType } from '@app/analytics'; import analytics from '@app/analytics/analytics'; @@ -61,18 +60,6 @@ import DeprecatedIcon from '@images/deprecated-status.svg?react'; // Tab path segment passed to getEntityPath — a route identifier, not user-visible copy. const INCIDENTS_TAB_NAME = 'Incidents'; -const StyledMoreIcon = styled(MoreVertOutlinedIcon)` - &&& { - display: flex; - font-size: 20px; - padding: 2px; - - :hover { - color: ${(p) => p.theme.colors.textBrand}; - } - } -`; - interface Options { hideDeleteMessage?: boolean; skipDeleteWait?: boolean; @@ -144,7 +131,7 @@ const EntityDropdown = (props: Props) => { const [isChangeHistoryOpen, setIsChangeHistoryOpen] = useState(false); const handleUpdateDeprecation = async (deprecatedStatus: boolean) => { - message.loading({ content: tcf('updating') }); + toast.loading(tcf('updating')); try { await updateDeprecation({ variables: { @@ -156,20 +143,17 @@ const EntityDropdown = (props: Props) => { }, }, }); - message.destroy(); - message.success({ content: t('deprecation.updated'), duration: 2 }); + toast.destroy(); + toast.success(t('deprecation.updated'), { duration: 2 }); analytics.event({ type: EventType.SetDeprecation, entityUrns: [urn], deprecated: deprecatedStatus, }); } catch (e: unknown) { - message.destroy(); + toast.destroy(); if (e instanceof Error) { - message.error({ - content: t('deprecation.updateError', { errorMessage: e.message || '' }), - duration: 2, - }); + toast.error(t('deprecation.updateError', { errorMessage: e.message || '' }), { duration: 2 }); } } refetchForEntity?.(); @@ -197,7 +181,7 @@ const EntityDropdown = (props: Props) => { icon: Link, onClick: () => { navigator.clipboard.writeText(pageUrl); - message.info(t('menuItem.copiedUrl'), 1.2); + toast.info(t('menuItem.copiedUrl'), { duration: 1.2 }); }, }); } @@ -516,7 +500,7 @@ const EntityDropdown = (props: Props) => { return ( <> - + {isCreateTermModalVisible && ( { - message.loading({ content: tcf('updating') }); + toast.loading(tcf('updating')); try { await updateDeprecation({ variables: { @@ -34,20 +42,17 @@ export default function UpdateDeprecationMenuAction() { }, }, }); - message.destroy(); - message.success({ content: t('deprecation.updated'), duration: 2 }); + toast.destroy(); + toast.success(t('deprecation.updated'), { duration: 2 }); analytics.event({ type: EventType.SetDeprecation, entityUrns: [urn], deprecated: deprecatedStatus, }); } catch (e: unknown) { - message.destroy(); + toast.destroy(); if (e instanceof Error) { - message.error({ - content: t('deprecation.updateError', { errorMessage: e.message || '' }), - duration: 2, - }); + toast.error(t('deprecation.updateError', { errorMessage: e.message || '' }), { duration: 2 }); } } refetchForEntity?.(); @@ -62,8 +67,12 @@ export default function UpdateDeprecationMenuAction() { : t('deprecation.markUnTooltip', { entityName: entityRegistry.getEntityName(entityType) }) } > - !entityData?.deprecation?.deprecated ? setIsDeprecationModalVisible(true) @@ -71,8 +80,8 @@ export default function UpdateDeprecationMenuAction() { } data-testid="entity-menu-deprecate-button" > - - + + {isDeprecationModalVisible && ( void; - refetch?: () => void; + refetch?: (result?: DeprecationModalResult) => void; zIndexOverride?: number; }; const SCHEMA_FIELD_PREFIX = 'urn:li:schemaField:'; +const FieldGroup = styled.div` + display: flex; + flex-direction: column; + gap: 16px; +`; + +const ReplacementControls = styled.div` + align-self: flex-start; +`; + export const UpdateDeprecationModal = ({ urns, resourceRefs, onClose, refetch, zIndexOverride }: Props) => { const { t } = useTranslation('entity.shared.entityDropdown'); const { t: tc } = useTranslation('common.actions'); const { t: tcf } = useTranslation('common.feedback'); const { entityWithSchema } = useGetEntityWithSchema(); const schemaMetadata: any = entityWithSchema?.schemaMetadata || undefined; + const entityRegistry = useEntityRegistry(); const [batchUpdateDeprecation] = useBatchUpdateDeprecationMutation(); - const [isReplacementModalVisible, setIsReplacementModalVisible] = React.useState(false); - const [replacementUrn, setReplacementUrn] = React.useState(null); - const entityRegistry = useEntityRegistry(); + const [isReplacementModalVisible, setIsReplacementModalVisible] = useState(false); + const [replacementUrn, setReplacementUrn] = useState(null); + const [note, setNote] = useState(''); + const [decommissionTime, setDecommissionTime] = useState(undefined); const isDeprecatingFields = !!resourceRefs && resourceRefs.length > 0 && resourceRefs[0].subResourceType === SubResourceType.DatasetField; @@ -55,23 +71,16 @@ export const UpdateDeprecationModal = ({ urns, resourceRefs, onClose, refetch, z skip: !replacementUrn || replacementUrn?.startsWith(SCHEMA_FIELD_PREFIX), }); - const [form] = Form.useForm(); - - const handleClose = () => { - form.resetFields(); - onClose(); - }; - - const handleOk = async (formData: any) => { - message.loading({ content: tcf('updating') }); + const handleSubmit = async () => { + toast.loading(tcf('updating')); try { await batchUpdateDeprecation({ variables: { input: { resources: resourceRefs || urns.map((resourceUrn) => ({ resourceUrn })), deprecated: true, - note: formData.note, - decommissionTime: formData.decommissionTime && formData.decommissionTime.unix() * 1000, + note, + decommissionTime: decommissionTime ? decommissionTime.unix() * 1000 : null, replacement: replacementUrn, }, }, @@ -82,136 +91,132 @@ export const UpdateDeprecationModal = ({ urns, resourceRefs, onClose, refetch, z deprecated: true, resources: isDeprecatingFields ? resourceRefs : undefined, }); - message.destroy(); - message.success({ content: t('deprecation.updated'), duration: 2 }); + toast.destroy(); + toast.success(t('deprecation.updated'), { duration: 2 }); } catch (e: unknown) { - message.destroy(); + toast.destroy(); if (e instanceof Error) { - message.error( - handleBatchError(urns, e, { - content: t('deprecation.updateError', { errorMessage: e.message || '' }), - duration: 2, - }), - ); + const fallback = { + content: t('deprecation.updateError', { errorMessage: e.message || '' }), + duration: 2, + }; + const { content, duration } = handleBatchError(urns, e, fallback); + toast.error(content, { duration }); } } - refetch?.(); - handleClose(); + refetch?.({ + note: note || null, + decommissionTime: decommissionTime ? decommissionTime.unix() * 1000 : null, + replacement: replacementData?.entities?.[0] ?? null, + }); + onClose(); }; return ( -
- +