diff --git a/datahub-web-react/src/app/domain/CreateDomainModal.tsx b/datahub-web-react/src/app/domain/CreateDomainModal.tsx index 629298e479..7ea2b3fdbb 100644 --- a/datahub-web-react/src/app/domain/CreateDomainModal.tsx +++ b/datahub-web-react/src/app/domain/CreateDomainModal.tsx @@ -3,7 +3,7 @@ import styled from 'styled-components'; import { message, Button, Input, Modal, Typography, Form, Collapse, Tag } from 'antd'; import { useCreateDomainMutation } from '../../graphql/domain.generated'; import { useEnterKeyListener } from '../shared/useEnterKeyListener'; -import { groupIdTextValidation } from '../shared/textUtil'; +import { validateCustomUrnId } from '../shared/textUtil'; import analytics, { EventType } from '../analytics'; const SuggestedNamesGroup = styled.div` @@ -156,7 +156,7 @@ export default function CreateDomainModal({ onClose, onCreate }: Props) { rules={[ () => ({ validator(_, value) { - if (value && groupIdTextValidation(value)) { + if (value && validateCustomUrnId(value)) { return Promise.resolve(); } return Promise.reject(new Error('Please enter a valid Domain id')); diff --git a/datahub-web-react/src/app/entity/shared/EntityDropdown/CreateGlossaryEntityModal.tsx b/datahub-web-react/src/app/entity/shared/EntityDropdown/CreateGlossaryEntityModal.tsx index 743712cd06..15f9cc7ca9 100644 --- a/datahub-web-react/src/app/entity/shared/EntityDropdown/CreateGlossaryEntityModal.tsx +++ b/datahub-web-react/src/app/entity/shared/EntityDropdown/CreateGlossaryEntityModal.tsx @@ -1,7 +1,7 @@ import React, { useState } from 'react'; import styled from 'styled-components/macro'; import { EditOutlined } from '@ant-design/icons'; -import { message, Button, Input, Modal, Typography, Form } from 'antd'; +import { message, Button, Input, Modal, Typography, Form, Collapse } from 'antd'; import DOMPurify from 'dompurify'; import { useCreateGlossaryTermMutation, @@ -13,6 +13,7 @@ import NodeParentSelect from './NodeParentSelect'; import { useEntityData, useRefetch } from '../EntityContext'; import analytics, { EventType } from '../../../analytics'; import DescriptionModal from '../components/legacy/DescriptionModal'; +import { validateCustomUrnId } from '../../../shared/textUtil'; const StyledItem = styled(Form.Item)` margin-bottom: 0; @@ -37,6 +38,7 @@ function CreateGlossaryEntityModal(props: Props) { const entityData = useEntityData(); const [form] = Form.useForm(); const entityRegistry = useEntityRegistry(); + const [stagedId, setStagedId] = useState(undefined); const [stagedName, setStagedName] = useState(''); const [selectedParentUrn, setSelectedParentUrn] = useState(entityData.urn); const [documentation, setDocumentation] = useState(''); @@ -55,6 +57,7 @@ function CreateGlossaryEntityModal(props: Props) { mutation({ variables: { input: { + id: stagedId?.length ? stagedId : undefined, name: stagedName, parentNode: selectedParentUrn || null, description: sanitizedDescription || null, @@ -167,6 +170,42 @@ function CreateGlossaryEntityModal(props: Props) { /> )} + + Advanced} key="1"> + + {entityRegistry.getEntityName(props.entityType)} Id + + } + > + + By default, a random UUID will be generated to uniquely identify this entity. If + you'd like to provide a custom id, you may provide it here. Note that it should be + unique across the entire Glossary. Be careful, you cannot easily change the id after + creation. + + ({ + validator(_, value) { + if (value && validateCustomUrnId(value)) { + return Promise.resolve(); + } + return Promise.reject(new Error('Please enter a valid entity id')); + }, + }), + ]} + > + setStagedId(event.target.value)} + /> + + + + ); diff --git a/datahub-web-react/src/app/identity/group/CreateGroupModal.tsx b/datahub-web-react/src/app/identity/group/CreateGroupModal.tsx index 2033d905a1..214cb25176 100644 --- a/datahub-web-react/src/app/identity/group/CreateGroupModal.tsx +++ b/datahub-web-react/src/app/identity/group/CreateGroupModal.tsx @@ -2,7 +2,7 @@ import React, { useState } from 'react'; import { message, Button, Input, Modal, Typography, Form, Collapse } from 'antd'; import { useCreateGroupMutation } from '../../../graphql/group.generated'; import { useEnterKeyListener } from '../../shared/useEnterKeyListener'; -import { groupIdTextValidation } from '../../shared/textUtil'; +import { validateCustomUrnId } from '../../shared/textUtil'; import analytics, { EventType } from '../../analytics'; import { CorpGroup, EntityType } from '../../../types.generated'; @@ -134,7 +134,7 @@ export default function CreateGroupModal({ onClose, onCreate }: Props) { rules={[ () => ({ validator(_, value) { - if (value && groupIdTextValidation(value)) { + if (value && validateCustomUrnId(value)) { return Promise.resolve(); } return Promise.reject(new Error('Please enter correct Group name')); diff --git a/datahub-web-react/src/app/shared/textUtil.ts b/datahub-web-react/src/app/shared/textUtil.ts index 5a258aff36..ea8522683e 100644 --- a/datahub-web-react/src/app/shared/textUtil.ts +++ b/datahub-web-react/src/app/shared/textUtil.ts @@ -19,7 +19,7 @@ export function capitalizeFirstLetterOnly(str?: string | null) { return str.charAt(0).toUpperCase() + str.slice(1); } -export function groupIdTextValidation(str: string) { +export function validateCustomUrnId(str: string) { if (str.indexOf(' ') > 0) return false; if (str.indexOf(',') > 0) return false; if (str.indexOf('(') > 0) return false;